SQL中WHERE变量ISNULL条件导致全表扫描问题的解决
⽅法
复制代码代码如下:
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的索引,另外agisnull的用法
e=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的⽅案

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。