SQL中WHERE变量IS NULL条件导致全表扫描问题的解决方法
时间:2024-01-13 12:58:24
SET @SQL = 'SELECT * FROM Comment with(nolock) WHERE 1=1
And (@ProjectIds Is Null or ProjectId = @ProjectIds)
And (@Scores is null or Score =@Scores)'
印象中记得,以前在做Oracle开发时,这种写法是会导致全表扫描的,用不上索引,不知道Sql Server里是否也是一样呢,于是做一个简单的测试
1、建立测试用的表结构和索引:
CREATE TABLE aaa(id int IDENTITY, NAME VARCHAR(12), age INT)
go
CREATE INDEX idx_age ON aaa (age)
GO
2、插入1万条测试数据:
DECLARE @i INT;
SET @i=0;
WHILE @i<10000
BEGIN
INSERT INTO aaa (name, age)VALUES(CAST(@i AS VARCHAR), @i)
SET @i=@i+1;
END
GO
3、先开启执行计划显示:
在SQL Server Management Studio的查询窗口里,右击窗口任意位置,选择“包含实际的执行计划”:
4、开始测试,用下面的SQL进行测试:
DECLARE @i INT;
SET @i=100
SELECT * FROM aaa WHERE (@i IS NULL OR age = @i)
SELECT * FROM aaa WHERE (age = @i OR @i IS NULL)
SELECT * FROM aaa WHERE age=isnull(@i, age)
SELECT * FROM aaa WHERE age = @i
测试结果如下:
可以看到,即使@i有值,不管@i IS NULL是放在前面还是放在后面,都无法用到age的索引,另外age=ISNULL(@i,age)也用不上索引
最终结论,SQL Server跟ORACLE一样,如果条件里加了 变量 IS NULL,都会导致全表扫描。
建议SQL改成:
DECLARE @i INT;
SET @i=100
DECLARE @sql NVARCHAR(MAX)
SET @sql = 'SELECT * FROM aaa'
IF @i IS NOT NULL
SET @sql = @sql + ' WHERE age = @i'
EXEC sp_executesql @sql, N'@i int', @i
当然,如果只有一个条件,可以设计成2条SQL,比如:
DECLARE @i INT;
SET @i=100
IF @i IS NOT NULL
SELECT * FROM aaa WHERE age = @i
ELSE
SELECT * FROM aaa
但是,如果条件多了,SQL数目也变得更多,所以建议用EXEC的方案
标签:sql,ISNULL,全表扫描
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
python程序中调用其他程序的实现
2021-08-07 12:33:16
js中更短的 Array 类型转换
2024-04-28 09:47:22
python爬虫urllib中的异常模块处理
2022-12-06 10:42:33
![](https://img.aspxhome.com/file/2023/9/87699_0s.png)
python提取word文件中的图片并上传阿里云OSS
2021-02-01 10:52:25
![](https://img.aspxhome.com/file/2023/4/107964_0s.png)
Python海象运算符超详细讲解
2023-08-04 17:26:19
![](https://img.aspxhome.com/file/2023/2/102762_0s.jpg)
win2008下mysql8.0.11升级mysql8.0.17版本详细步骤
2024-01-13 18:04:32
![](https://img.aspxhome.com/file/2023/6/128046_0s.png)
Python爬取新型冠状病毒“谣言”新闻进行数据分析
2021-06-14 04:47:33
![](https://img.aspxhome.com/file/2023/8/72948_0s.jpg)
Python合并pdf文件的工具
2021-09-09 23:28:47
![](https://img.aspxhome.com/file/2023/3/77713_0s.png)
python 进程 进程池 进程间通信实现解析
2022-07-05 07:38:28
详解Python_shutil模块
2023-06-24 00:32:19
MySQL下载安装、配置与使用教程详细版(win7x64)
2024-01-22 16:44:50
![](https://img.aspxhome.com/file/2023/2/88492_0s.jpg)
使用SAE部署Python运行环境的教程
2021-02-21 14:26:54
Python实现随机生成手机号及正则验证手机号的方法
2021-05-30 01:41:27
Mysql使用kill命令解决死锁问题(杀死某条正在执行的sql语句)
2024-01-24 06:36:03
Go操作redis与redigo的示例解析
2024-04-28 09:12:38
mysql如何通过当前排序字段获取相邻数据项
2024-01-13 02:24:25
PHP开发中常见的安全问题详解和解决方法(如Sql注入、CSRF、Xss、CC等)
2023-10-02 23:03:06
mysql中普通索引和唯一索引的效率对比
2010-12-08 16:03:00
![](https://img.aspxhome.com/file/UploadPic/201012/8/2010128165343945s.jpg)
golang设置http response响应头与填坑记录
2024-05-21 10:22:24
![](https://img.aspxhome.com/file/2023/9/123989_0s.png)
MySQL prepare语句的SQL语法
2024-01-20 03:14:08