
SQL Server-聚焦WHERE Column = @Param OR @Param IS NULL有问题?
发布日期:2021-05-08 23:23:02
浏览次数:28
分类:博客文章
本文共 2174 字,大约阅读时间需要 7 分钟。
前言
上一篇我们讲完SQL动态查询,本节我们继续来讲解SQL动态查询中存在的问题。
SQL动态查询条件筛选过滤
当我们创建存储过程调用存储过程时,若筛选条件有值则过滤,没有值则返回所行记录,类似如下查询:
WHERE (SomeColumn=@col OR @col IS NULL)
这样查询会存在什么问题呢?性能会不会有问题呢,这个是我们本节需要深入探讨的问题。
接下来我们创建如下测试表并插入测试数据,如下:
CREATE TABLE Test ( SomeCol1 INT NOT NULL , Somecol2 INT NOT NULL ) INSERT Test SELECT number , low FROM master..spt_values WHERE TYPE = 'p' CREATE INDEX ix_col2 ON Test(Somecol2)GO
对于动态SQL条件筛选过滤我们利用WHERE 1 = 1来拼接。接下来我们使用一般SQL语句和动态查询并比较其IO,如下:
SET STATISTICS IO ONGO DECLARE @col INTSELECT @col = 1 SELECT SomeCol2 FROM TestWHERE 1 =1AND (SomeCol2=@col OR @col IS NULL) GO DECLARE @col INTSELECT @col = 1 DECLARE @SQL NVARCHAR(4000) SET @SQL = 'SELECT SomeCol2 FROM Test WHERE 1 =1' IF @col IS NOT NULL SET @SQL = @SQL + ' AND SomeCol2=@InnerParamcol ' EXEC sp_executesql @SQL,N'@InnerParamcol INT',@col SET STATISTICS IO OFFGO我们能够看到动态SQL查询逻辑读取只读取2次,而另外一般SQL语句查询逻辑读取7次,同时我们看到SQL动态查询计划执行的是索引查找,而一般SQL语句则是索引扫描。
看来执行一般SQL语句不会走索引查找,将导致性能问题,在开头我们就讲过筛选条件有值则过滤,无值则查询所有数据,那么我们完全可以借助ISNULL来查询,下面我们用ISNULL来改变一般语句筛选条件,看看是否会走索引查找呢?
SET STATISTICS IO ONGO DECLARE @col INTSELECT @col = 1 SELECT SomeCol2FROM dbo.TestWHERE 1 = 1AND SomeCol2 = ISNULL(@col,SomeCol2)
我们看到结果依然是走索引扫描,没有任何改变。是不是就没有解决之道了呢?我们来改变一般SQL语句查询方式,如下:
DECLARE @col INTSELECT @col = 1IF @Col IS NULL SELECT SomeCol2 FROM Test WHERE 1 = 1ELSE SELECT SomeCol2 FROM dbo.Test WHERE 1 = 1 AND SomeCol2 = @colGO
如上只能是勉勉强强解决了问题,因为只是针对一个参数,如果有多个参数要进行IF...ELSE..,那可就傻逼了。从本质上解决这个问题我们需要利用可选项重新编译。如下:
SET STATISTICS IO ONGO DECLARE @col INTSELECT @col = 1 SELECT SomeCol2 FROM dbo.TestWHERE 1 =1AND (SomeCol2 = @col OR @col IS NULL)OPTION(RECOMPILE) GO DECLARE @col INTSELECT @col = 1 DECLARE @SQL NVARCHAR(4000) SET @SQL = 'SELECT SomeCol2 FROM dbo.Test WHERE 1 =1' IF @col IS NOT NULL SET @SQL = @SQL + ' AND SomeCol2 = @InnerParamcol ' EXEC sp_executesql @SQL,N'@InnerParamcol INT',@col SET STATISTICS IO OFFGO
总结
当利用条件筛选过滤数据时,如果条件有值则过滤,否则返回所有行记录。如果执行一般SQL语句和动态SQL,那么动态SQL会走索引查找,而一般SQL语句将导致索引扫描,此时需要加上OPTION(RECOMPILE)才走索引查找。
发表评论
最新留言
感谢大佬
[***.8.128.20]2025年04月20日 14时53分25秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Centos 7.5 SSH改别的端口连接不上,只有默认端口才行(未解决)
2025-03-31
Centos 7.5 如何安装VMware Tools工具
2025-03-31
Centos 7.5 新磁盘创建和挂载XFS文件系统
2025-03-31
Centos 7.5安装safe-rm,防止rm -rf /命令误删除文件
2025-03-31
CentOS 7.X 系统安装及优化
2025-03-31
Centos 7下安装php+mysql+nginx+wordpress教程新版
2025-03-31
CentOS 7之Postfix部署系列 (一) CentOS安装
2025-03-31
flask框架面向移动端的虚拟物品订购平台毕设源码+论文
2025-03-31
flask框架飞机订票管理系统(毕设源码+论文)
2025-03-31
flask框架餐饮管理系统毕设源码+论文
2025-03-31
flask框架高性能教学资源平台设计与实现(毕设源码+论文)
2025-03-31
flask框架高校助学及勤工俭学管理系统(毕设源码+论文)
2025-03-31
flask框架高校图书管理系统设计与实现(毕设源码+论文)
2025-03-31
flask框架高校招生预报管理系统(毕设源码+论文)
2025-03-31
flask框架高校教师个人数字档案(毕设源码+论文)
2025-03-31
flask框架高校毕业生选题系统(毕设源码+论文)
2025-03-31
flask框架高校竞赛信息管理系统(毕设源码+论文)
2025-03-31
flask框架魔方教学网站毕设源码+论文
2025-03-31
Flask解决跨域访问问题(Access to XMLHttpRequest at ‘http://127.0.0.1:500been blocked by CORS policy: No ‘Acc)
2025-03-31
Flatterer: 快速JSON转换工具使用指南
2025-03-31