SQL Server解惑——查询条件IN中能否使用变量
在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中能否使用变量的更多相关文章
- SQL Server解惑——为什么你的查询结果超出了查询时间范围
原文:SQL Server解惑--为什么你的查询结果超出了查询时间范围 废话少说,直接上SQL代码(有兴趣的测试验证一下),下面这个查询语句为什么将2008-11-27的记录查询出来了呢?这个是同事遇 ...
- 【转】Sql Server参数化查询之where in和like实现之xml和DataTable传参
转载至: http://www.cnblogs.com/lzrabbit/archive/2012/04/29/2475427.html 在上一篇Sql Server参数化查询之where in和li ...
- 50种方法优化SQL Server数据库查询
查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 ...
- 优化SQL Server数据库查询方法
SQL Server数据库查询速度慢的原因有很多,常见的有以下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列 ...
- 转载 50种方法优化SQL Server数据库查询
原文地址 http://www.cnblogs.com/zhycyq/articles/2636748.html 50种方法优化SQL Server数据库查询 查询速度慢的原因很多,常见如下几种: 1 ...
- Sql Server参数化查询之where in和like实现之xml和DataTable传参 (转)
在上一篇Sql Server参数化查询之where in和like实现详解中介绍了在Sql Server使用参数化查询where in的几种实现方案,遗漏了xml和表值参数,这里做一个补充 文章导读 ...
- CASE函数 sql server——分组查询(方法和思想) ref和out 一般处理程序结合反射技术统一执行客户端请求 遍历查询结果集,update数据 HBuilder设置APP状态栏
CASE函数 作用: 可以将查询结果集的某一列的字段值进行替换 它可以生成一个新列 相当于switch...case和 if..else 使用语法: case 表达式/字段 when 值 then ...
- C#构造方法(函数) C#方法重载 C#字段和属性 MUI实现上拉加载和下拉刷新 SVN常用功能介绍(二) SVN常用功能介绍(一) ASP.NET常用内置对象之——Server sql server——子查询 C#接口 字符串的本质 AJAX原生JavaScript写法
C#构造方法(函数) 一.概括 1.通常创建一个对象的方法如图: 通过 Student tom = new Student(); 创建tom对象,这种创建实例的形式被称为构造方法. 简述:用来初 ...
- 08Microsoft SQL Server 数据查询
Microsoft SQL Server 数据查询 单表查询所有列 --查询所有行所有列 select all * from table; --查询不重复行的所有列 select distinct * ...
随机推荐
- DVWA各等级XSS
xss原理及基本介绍 XSS,全称Cross Site Scripting,即跨站脚本攻击,某种意义上也是一种注入攻击,是指攻击者在页面中注入恶意的脚本代码,当受害者访问该页面时,恶意代码会在其浏览器 ...
- vue seo 优化
预渲染prerender-spa-plugin 如果你只是用来改善少数营销页面(例如 /, /about, /contact 等)的 SEO,那么你可能需要预渲染.无需使用 web 服务器实时动态编译 ...
- Spring Cloud Alibaba (一): SpringCloud与SpringBoot版本选型
前言 近年SpringCloud与SpringBoot更新迭代非常频繁,导致我们对两者的版本选型非常的困难.若是版本选择有问题, 会导致开发中调试兼容性占用非常多的得必要时间. SpringClo ...
- [GXYCTF2019]禁止套娃(无参RCE)
[GXYCTF2019]禁止套娃 1.扫描目录 扫描之后发现git泄漏 使用githack读取泄漏文件 <?php include "flag.php"; echo &quo ...
- angular8 大地老师学习笔记---第八课
/*ViewChild获取dom节点 1.模板中给dom起一个名字 <div #myBox> 我是一个dom节点 </div> 2.在业务逻辑里面引入ViewChild imp ...
- 开发你的第一个NCS(Zephyr)应用程序
Nordic有2套并存的SDK:老的nRF5 SDK和新的NCS SDK,两套SDK相互独立,大家选择其中一套进行开发即可.一般而言,如果你选择的芯片是nRF51或者nRF52系列,那么推荐使用nRF ...
- Python 学习笔记(上)
Python 学习笔记(上) 这份笔记是我在系统地学习python时记录的,它不能算是一份完整的参考,但里面大都是我觉得比较重要的地方. 目录 Python 学习笔记(上) 基础知识 基本输入输出 模 ...
- python 做回归
1 一元线性回归 线性回归是一种简单的模型,但受到广泛应用,比如预测商品价格,成本评估等,都可以用一元线性模型.y = f(x) 叫做一元函数,回归意思就是根据已知数据复原某些值,线性回归(regre ...
- python初学者-从键盘输入两个数判断大小
a = int(input("a:")) b = int(input("b:")) if a > b : print(a) else : print(b)
- 微服务痛点-基于Dubbo + Seata的分布式事务(TCC模式)
前言 Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务.Seata 将为用户提供了 AT.TCC.SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案. ...