经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MS SQL Server » 查看文章
如何优雅的使用 参数 is null而不导致全表扫描(破坏索引)
来源:cnblogs  作者:托大人  时间:2019/4/9 9:25:48  对本文有异议

 

相信大家在很多实际业务中(特别是后台系统)会使用到各种筛选条件来筛选结果集

首先添加测试数据

  1. CREATE TABLE TempList(Id int IDENTITY,Name VARCHAR(12), Age INT)
  2. go
  3. CREATE INDEX idx_age ON TempList (Age)
  4. GO
  5.  
  6.  
  7. DECLARE @i INT;
  8. SET @i=0;
  9. WHILE @i<10000
  10. BEGIN
  11. INSERT INTO TempList (Name, Age)VALUES(CAST(@i AS VARCHAR),@i)
  12. SET @i=@i+1;
  13. END
  14. GO

 

 

1.有使用EXEC来避免全表扫描

  1. DECLARE @age INT=666;
  2. DECLARE @sql NVARCHAR(MAX)
  3. SET @sql = 'SELECT * FROM TempList'
  4.  
  5. IF @age IS NOT NULL
  6. SET @sql = @sql + ' WHERE Age = @age'
  7. EXEC sp_executesql @sql, N'@age int', @age

或者条件少的情况下

  1. DECLARE @age INT=666;
  2. IF @age IS NOT NULL
  3. SELECT * FROM TempList WHERE Age = @age
  4. ELSE
  5. SELECT * FROM TempList

2.使用IS NULL来实现

  1. DECLARE @age INT=666;
  2. SELECT * FROM TempList WHERE (@age IS NULL OR Age = @age)
  3. SELECT * FROM TempList WHERE (Age = @age OR @age IS NULL)
  4. SELECT * FROM TempList WHERE Age=isnull(@age, Age)

 

第一种方案,不会破坏索引,但冗余的代码看起来让人难受

第二种方案,会导致全表扫描(破坏索引)

 

以上是网上查阅的资料,方案二不符合SARG,问题在OR,如果我不使用OR,用AND呢

  1. DECLARE @age INT=666;
  2. SELECT * FROM TempList WHERE @age IS NOT NULL and Age = @age

 

 

版权声明:本文原创发表于 博客园,作者为 托大人 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。

 

原文链接:http://www.cnblogs.com/robots/p/10671802.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号