如果我有一个运行带有可选参数的搜索的查询,我通常的方法是传入NULL
以获取任何未使用的条件,并且有WHERE
子句看起来像
WHERE (@Param IS NULL OR Field=@Param) AND (@Param2 IS NULL OR Field2=@Param2)
如果我的条件可能要稍微复杂一些,比如LIKE
条款,SQL Server
将评估IS NULL
然后短路更复杂的条件?我是否可以在执行计划中查看是否存在?这种行为是否依赖于优化器选择的计划,这样我的开发和生产环境中的答案可能会有所不同(我有限制地查看生产中发生了什么,所以我希望行为一致)
答案 0 :(得分:2)
请参阅this answer有关基于参数的查询的类似问题。
在他的回答中,他链接到一篇优秀的文章:Dynamic Search Conditions in T-SQL by Erland Sommarskog
答案 1 :(得分:0)
我使用CASE语句。
所以你的是这样的:
WHERE (@Param IS NULL OR Field=@Param) AND (@Param2 IS NULL OR Field2=@Param2)
我会这样写:
WHERE CASE WHEN @Param IS NULL THEN 1 ELSE Field END = CASE WHEN @Param IS NULL THEN 1 ELSE @Param END AND
CASE WHEN @Param2 IS NULL THEN 1 ELSE Field2 END = CASE WHEN @Param2 IS NULL THEN 1 ELSE @Param2 END
查看您获得的查询执行计划,在很多情况下,当您使用OR条件时,查询优化器使用表扫描。您也可以将'='替换为'like'等,实际上您甚至可以将其包含在case语句中。因此,您可以将{='替换为CASE WHEN @Param3 = 'eq' THEN = ELSE LIKE END
希望这有帮助。
答案 2 :(得分:0)
我找到了一个更实用的解决方案,它避免了使用动态SQL。
假设您有一个位字段,参数为1、0或(null =两者)。然后使用以下SQL:
在a.FIELD = CASE当ISNULL(@ PARAM,-1)=-1的情况下,然后a.FIELD ELSE @PARAM结束
换句话说:如果您不为@param提供显式值,则告诉A.field = a.field始终为真。对于可为空的字段,您需要在该字段上应用ISNULL,以免null = null不会通过。
示例:在INT字段上可以为空,
AND ISNULL(a.CALL_GENERAL_REQUIREMENTS,-1)=CASE WHEN ISNULL(@CALL_GENERAL_REQUIREMENTS,-2)=-2 THEN ISNULL(a.CALL_GENERAL_REQUIREMENTS,-1) ELSE @CALL_GENERAL_REQUIREMENTS END
如您所见,我将-2应用于参数@CALL_GENERAL_REQUIREMENTS的空值,这是因为要选择的实际值可以为0(未传递),1(已传递),-1(尚未评估)。因此,-2表示请勿在此字段上选择
可为空的字符串字段的示例:
AND ISNULL(a.CALL_RESULT,'')=CASE WHEN ISNULL(@CALL_RESULT,'')='' THEN ISNULL(a.CALL_RESULT,'') ELSE @CALL_RESULT END
所有功能都是一种魅力,并且避免了在创建带有串联的动态SQL字符串时的麻烦,并且不需要分配特定权限就可以运行exec语句。
希望这对任何人都有帮助。
祝你有美好的一天