SQL中WHERE变量IS NULL条件导致全表扫描问题的解决方法

复制代码 代码如下:

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的方案

(0)
上一篇 2022年3月21日
下一篇 2022年3月21日

相关推荐