【问题标题】:How to use CASE in WHERE clause for short circuiting CONTAINS如何在 WHERE 子句中使用 CASE 短路 CONTAINS
【发布时间】:2014-08-18 20:22:49
【问题描述】:

我有一个用于搜索的存储过程,它带有几个可选参数。其中之一是@keywords 定义为

@keywords nvarchar(1000) = null,

如果@keywords为null或空字符串,我想短路,否则我需要搜索全文索引。我以前的逻辑是这样的:

WHERE
(@keywords IS NULL OR CONTAINS( (Title, CrossRef, company_name), @keywords))
AND
-- other search terms

但是,我刚刚发现 OR 不能保证短路,所以有时这会返回“空全文谓词”的错误。显然 CASE 应该保证短路,但是某些版本的 SQL server 有一个错误,情况并非如此。

这是我正在尝试的:

WHERE 
(1 = CASE
    WHEN @keywords IS NULL THEN 1
    WHEN @keywords = '""' THEN 1
    ELSE (CASE WHEN CONTAINS( (Title, CrossRef, company_name), @keywords) THEN 1 ELSE 0 END)
)
AND
-- other search terms

这仍然给出“空全文谓词”错误。我很乐意将 @keywords 替换为始终匹配的内容,但我也不知道该怎么做。

【问题讨论】:

    标签: sql-server


    【解决方案1】:

    既然您已经在使用 SP,为什么不直接将其放入 IF THEN ELSE 块中以实现您的短路逻辑。它不仅更容易阅读,优化器也会更喜欢它。

    【讨论】:

    • 据我了解,我不能只将 WHERE 子句的那一部分放在 IF 语句中。我必须把整个查询放进去,这意味着复制其余的查询。不过,这可能是这里最好的解决方案。
    • 您需要将查询的一个迭代放在 IF 块中,另一个放在 ELSE 中。基本上,您必须以两种不同的方式编写查询,并且 IF 将评估 @keywords 为 NULL 或空。如果是,请使用您的捷径逻辑。如果不是,不要。无论哪种情况,您最终都会得到一个针对该条件的定制 SQL 语句。
    【解决方案2】:

    这就是我最终要做的。在 SP 的顶部:

    DECLARE @fix_keywords nvarchar(1000)
    SET @fix_keywords = @keywords
    IF @keywords IS NULL OR @keywords = '' SET @fix_keywords = 'zqxvMatchNothing321'
    

    然后

    WHERE 
    (@keywords IS NULL OR @keywords = '' OR CONTAINS( (Title, CrossRef, company_name), @fix_keywords))
    AND
    -- other search terms
    

    我意识到这有点老套,但我认为这是我的最佳解决方案,因为我不必在 IF/ELSE 中复制整个查询。

    另一个可能的解决方案是使用动态 SQL。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-14
      • 1970-01-01
      相关资源
      最近更新 更多