我有一个表Table,在SQL Server数据库中有两列,PKColumn1和Column2。该表有一个聚簇索引,聚集在PKColumn1上。
如果我对这个表使用以下查询,我希望执行计划显示一个Clustered Index Seek。
SELECT PKColumn1
FROM Table
WHERE PKColumn1 = 1
它适当地做了。
如果我对这个表使用以下查询,我也希望执行计划显示一个Clustered Index Seek。
DECLARE @PKColumn1 INT = 1;
SELECT PKColumn1
FROM Table
WHERE (PKColumn1 = @PKColumn1 OR @PKColumn1 IS NULL)
但是我现在从执行计划中看到该表已经扫描。
为什么会这样?
答案 0 :(得分:3)
在您的第二个查询中,问题出在您的where子句中:
WHERE (PKColumn1 = @PKColumn1 OR @PKColumn1 IS NULL)
。
SQL Server不做任何短路(如c#||),这意味着即使表达式@PKColumn1 IS NULL
的计算结果为true,也无法保证sql server不会计算第二个表达式{{1 }}
<强>解决方案:强>
处理此类可选参数的最佳方法是使用动态SQL并动态构建查询。像......那样......
PKColumn1 = @PKColumn1
使用sp_executesql将缓存参数化的执行计划。当您有两个以上的可选参数时,这通常是个问题。