在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. oracle修改数据文件目录

    一.停库修改数据文件目录.文件名 1.当前数据文件目录 SQL> select file_name from dba_data_files; FILE_NAME ---------------- ...

  2. Goldengate搭建

    OGG进程 捕获进程(源端):捕获online redo log或者archived log中增量事务日志 传输进程(源端):把目标端落地的trail文件通过配置的路由信息传输到目标端 网络传输:tc ...

  3. SpringBoot集成Swagger2并配置多个包路径扫描

    1. 简介   随着现在主流的前后端分离模式开发越来越成熟,接口文档的编写和规范是一件非常重要的事.简单的项目来说,对应的controller在一个包路径下,因此在Swagger配置参数时只需要配置一 ...

  4. SpringBoot集成基于tobato的fastdfs-client实现文件上传下载和删除

    1. 简介   基于tobato的fastdfs-client是一个功能完善的FastDFS客户端工具,它是在FastDFS作者YuQing发布的客户端基础上进行了大量的重构,提供了上传.下载.删除. ...

  5. 微信小程序自动化,记录趟过的坑!

    项目思想:关键字+数据驱动混合测试 基于Android-微信小程序自动化的关键是:webview的切换 对于微信App来说如何从NATIVE切换到webview的过程 测试版本信息 1.微信版本:7. ...

  6. 抢先看:笔者亲历的2020年中国.NET开发者大会活动纪实

    2020年中国.NET开发者大会活动纪实 1 2020年12月19日的苏州工业园区,天公作美,阳光明媚,气象迷人,正是一个搞事的好日子.在这里,数百名中国.NET开发者们汇聚一堂,怀揣着激情和梦想,一 ...

  7. 单身狗福利!利用java实现每天给对象发情话,脱单指日可待!

    引言 最近看到一篇用js代码实现表白的文章,深有感触. 然后发现自己也可以用java代码实现,然后就开始写代码了,发现还挺有意思的,话不多说开搞 实现思路: 使用HttpClient远程获取彩虹屁生成 ...

  8. Linux系列之makefile的简单入门

    什么是makefile呢? 一个工程中的源文件不计其数,其按类型.功能.模块分别放在若干个目录中,makefile定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译, ...

  9. 在linux下搭建NFS服务器实现文件共享

    目录 一.关于NFS 二.搭建一台NFS服务器共享特定资源 三.调优 一.关于NFS 1.NFS是Network File System的简写,即网络文件系统.网络文件系统是FreeBSD支持的文件系 ...

  10. (六)、mkdir--创建目录make directory

    一.命令详解与命令格式 在文件系统中创建新的目录, 格式:mkdir   [-选项]   目录名 目录名既可以是相对路径名,也可是相对路径名 选项: -p或者--parent,创建指定路径中所有不存在 ...