我有几个使用动态SQL的存储过程。 我真的很想改变它们以使它们不动态,纯粹是因为它们可能因为错误处理而排除故障并改变它们非常烦人(点击错误信息并不能带你到错误)。我知道我可以选择文本并将其粘贴为常规SQL来帮助解决这个问题,但这非常令人沮丧。
我遇到的问题是,当查询不是动态时,查询运行得慢得多。具体来说,由于其灵活性增加,where子句在动态查询中要快得多。例如,static where子句类似于:
where
SomeColumn = case when @variable1 = 0 then SomeColumn else @variable1 end
and(
(@variable2 = -2 and SomeColumn2 = 1)
or (@variable2 = -1)
or (@variable2 = 0 and SomeColumn2 = 0 and SomeColumn3 = 0)
or (@variable2 = 1 and SomeColumn2 = 0 and SomeColumn3 > 0)
)
但是动态where子句将是:
where ' + @SomeCondition + @SomeCondition2 + '
使用这样的案例陈述:
declare @SomeCondition nvarchar(max) = case
when @variable3 = -2 then N'Condition 1'
when @variable3 = 0 then N'Condition 2'
when @variable3 = 1 then N'Condition 3'
else N''
end
我能想到的唯一解决方案是使用多个if
语句,并且只更改每个语句中的where子句,但这看起来非常浪费和耗时。
动态SQL还有其他替代方法吗? 如果做不到这个问题,我能做些什么来让sql-server正确指导错误吗?
答案 0 :(得分:3)
将OPTION (RECOMPILE)
添加到查询中。这将导致它在每次执行时重新编译,并且优化器足够智能,可以快捷方式并消除谓词,就像您现在使用动态SQL一样。
答案 1 :(得分:1)
或者,您可以使用ISNULL(NULLIF
语法,如下所示。但请谨慎使用,因为它可能会对性能产生负面影响。
where
SomeColumn = ISNULL(NULLIF(@variable1,''),SomeColumn) and
SomeColumn2 = ISNULL(NULLIF(@variable2,''),SomeColumn2) and
and so on..