在SQL Server的查询条件中,能否在IN里面使用变量呢? 如果可以的话,有没有需要注意的地方或一些限制呢?在回答这个问题前,我们先来看看这个例子:

IF EXISTS (SELECT 1 FROM sys.objects WHERE name='TEST' AND type='U')
BEGIN
    DROP TABLE TEST;
END
GO
CREATE TABLE TEST ( ID INT, NAME VARCHAR(16) );
GO
 
INSERT INTO dbo.TEST
SELECT 1, 'a'  UNION ALL
SELECT 2, 'b'  UNION ALL
SELECT 3, 'c'  UNION ALL
SELECT 4, 'a,b'UNION ALL
SELECT 5, '''b'',''c''' UNION ALL
SELECT 6, '''b';
GO

如下所示,如果查询条件里面,变量只有一个值,此时SQL是正常的。

DECLARE @name VARCHAR(16);
SET @name='a';
 
SELECT * FROM TEST WHERE name IN (@name);
GO
 
DECLARE @name VARCHAR(16);
SET @name='a,b';
 
SELECT * FROM TEST WHERE name IN (@name);
GO

如果我们想在查询条件IN里面输入多个值呢?假如有这样的一个需求,一个变量里面包含b和c的值,现在用'b|c’作为条件传入,对其进行拆分为变量'b'和'c', 想查出name=b 和name=c的记录,如下截图所示,SQL其实并没有按你所“设想/预想”的查出对应记录,而是将ID=5的记录查出来了

DECLARE @name1 VARCHAR(16);
DECLARE @name2 VARCHAR(16);
SET @name1='b|c';
SET @name2=REPLACE(@name1,'|',''',''')
SELECT @name2
 
SELECT * FROM TEST WHERE name IN (('''' + @name2 + ''''));

下面这个SQL也是同样的结果。

DECLARE @name1 VARCHAR(16);
DECLARE @name2 VARCHAR(16);
SET @name1='b|c';
SET @name2='''' + REPLACE(@name1,'|',''',''') +''''
SELECT @name2
 
SELECT * FROM TEST WHERE name IN (@name2 );

为什么出现了这样的结果呢? 查了大量的官方文档,没有看到关于这个问题的介绍和解释。如果一定要解释上面现象的情况的话,那么是因为SELECT * FROM TEST WHERE name IN (@name2 ); 其实转化为了SELECT * FROM TEST WHERE name =@name2; 也就是说,上面SQL并不会按你所“设想”的逻辑运算。而是做了一个转换,为什么说是这样的一个转换呢? 当然这也是一个猜想,上面构造的例子也是为了侧面验证这个猜想,另外,上面两个SQL实际执行计划的参数列表(Parameter List)也侧面印证了这个猜想。如果解析我们想要的结果,Parameter List应该是'b' 和‘c'

解决方案:

1:使用动态SQL

 

使用动态SQL解决问题,似乎没啥好说的,如下例子所示:

DECLARE @sql_cmd NVARCHAR(max);
DECLARE @name VARCHAR(16);
 
SET @name='b|c';
SET @sql_cmd='SELECT * FROM TEST WHERE name IN (''' + REPLACE(@name,'|',''',''') +''');'
 
EXEC sp_executesql @sql_cmd;

2:使用临时表或表变量

以这个例子来说,就是将字符串拆分,放入临时表或表变量,然后关联表也好,在IN里面使用子查询也OK。

3:借助STRING_SPLIT()

DECLARE @name VARCHAR(16);
 
SET @name='b|c';
SELECT *FROM  test WHERE name IN (SELECT value FROM STRING_SPLIT(@name, '|'))

注意:STRING_SPLIT函数只有较高版本才支持,SQL Server 2017或SQL Server 2016部分版本支持。

4:借助XML函数来解决问题

 

DECLARE @name VARCHAR(16);
DECLARE @xml_para XML;
 
SET @name = 'b|c';
SET @xml_para = CAST(( '<A>' + REPLACE(@name, '|', '</A><A>') + '</A>' ) AS XML);
 
 
SELECT  *
FROM    dbo.TEST
WHERE   NAME IN ( SELECT    A.value('.', 'varchar(max)') AS [Column]
                  FROM      @xml_para.nodes('A') AS FN ( A ) );

SQL Server解惑——查询条件IN中能否使用变量的更多相关文章

  1. SQL Server解惑——为什么你的查询结果超出了查询时间范围

    原文:SQL Server解惑--为什么你的查询结果超出了查询时间范围 废话少说,直接上SQL代码(有兴趣的测试验证一下),下面这个查询语句为什么将2008-11-27的记录查询出来了呢?这个是同事遇 ...

  2. 【转】Sql Server参数化查询之where in和like实现之xml和DataTable传参

    转载至: http://www.cnblogs.com/lzrabbit/archive/2012/04/29/2475427.html 在上一篇Sql Server参数化查询之where in和li ...

  3. 50种方法优化SQL Server数据库查询

    查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 ...

  4. 优化SQL Server数据库查询方法

    SQL Server数据库查询速度慢的原因有很多,常见的有以下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列 ...

  5. 转载 50种方法优化SQL Server数据库查询

    原文地址 http://www.cnblogs.com/zhycyq/articles/2636748.html 50种方法优化SQL Server数据库查询 查询速度慢的原因很多,常见如下几种: 1 ...

  6. Sql Server参数化查询之where in和like实现之xml和DataTable传参 (转)

    在上一篇Sql Server参数化查询之where in和like实现详解中介绍了在Sql Server使用参数化查询where in的几种实现方案,遗漏了xml和表值参数,这里做一个补充 文章导读 ...

  7. CASE函数 sql server——分组查询(方法和思想) ref和out 一般处理程序结合反射技术统一执行客户端请求 遍历查询结果集,update数据 HBuilder设置APP状态栏

    CASE函数   作用: 可以将查询结果集的某一列的字段值进行替换 它可以生成一个新列 相当于switch...case和 if..else 使用语法: case 表达式/字段 when 值 then ...

  8. C#构造方法(函数) C#方法重载 C#字段和属性 MUI实现上拉加载和下拉刷新 SVN常用功能介绍(二) SVN常用功能介绍(一) ASP.NET常用内置对象之——Server sql server——子查询 C#接口 字符串的本质 AJAX原生JavaScript写法

    C#构造方法(函数)   一.概括 1.通常创建一个对象的方法如图: 通过  Student tom = new Student(); 创建tom对象,这种创建实例的形式被称为构造方法. 简述:用来初 ...

  9. 08Microsoft SQL Server 数据查询

    Microsoft SQL Server 数据查询 单表查询所有列 --查询所有行所有列 select all * from table; --查询不重复行的所有列 select distinct * ...

随机推荐

  1. Robot Framework+adb框架自动化测试Android设备案例⑹——源码地址、测试报告

    一.源码地址 GitHub:https://github.com/xiongye105554598/DVR8010_AutoTest 二.测试报告

  2. 应用案例——高并发 WEB 服务器队列的应用

    在高并发 HTTP 反向代理服务器 Nginx 中,存在着一个跟性能息息相关的模块 - 文件缓存. 经常访问到的文件会被 nginx 从磁盘缓存到内存,这样可以极大的提高 Nginx 的并发能力,不过 ...

  3. oracle 11g修改归档日志目录及大小

    1.查看当前归档日志目录 SQL> show parameter recovery NAME TYPE VALUE ------------------------------------ -- ...

  4. SpringBoot整合Swagger2详细教程

    1. 简介   随着前后端分离开发模式越来越流行,编写接口文档变成了开发人员非常头疼的事.而Swagger是一个规范且完整的web框架,用于生成.描述.调用可视化的RESTful风格的在线接口文档,并 ...

  5. Springboot mini - Solon详解(八)- Solon的缓存框架使用和定制

    Springboot min -Solon 详解系列文章: Springboot mini - Solon详解(一)- 快速入门 Springboot mini - Solon详解(二)- Solon ...

  6. jvm基本结构和解析

    jvm的基本结构图如下 这只是代表我的个人理解  不是很深刻  欢迎各类大神进行补充和纠正 jvm之所以强大就是因为他从软件层面屏蔽不用操作系统在底层硬件与指令上的区别,从而可以在不同系统上兼容 主要 ...

  7. Go语言(1)——程序结构

    程序结构 基础部分仅仅列举和其他语言不一样的地方(C语言为例). 声明 Go语言有四个主要声明:var.const.type.func,类似于C语言中的变量,常量,结构体和函数. package ma ...

  8. Missing Private key解决方案——IOS证书 .cer 以p12文件以及配置方案

    一个苹果证书怎么多次使用--导出p12文件 为什么要导出.p12文件 因为苹果规定 .cer证书只能存在于一台机器上,因此 如果另一台电脑想要用的话,需要导出为.p12 file ,安装到另一台没有安 ...

  9. [OI笔记]后缀自动机

    本来没打算写的,不过想想看后缀自动机的理论看了两三天了才有点懂(我太傻了)-下周期末考的话大概要去复习一下文化课感觉回来又要忘得差不多,还是开篇blog记一下好了. 相关的资料: cls当年的课件:2 ...

  10. SQL注入-DNS注入(一)

    这篇文章相对来说比较入门,参考的文章是:https://www.jianshu.com/p/c805209244c2 0x00前言 前段时间在做盲注 分别是基于时间和基于布尔型的 说真的 这两种盲注真 ...