Sql server 如何在WHERE子句中使用短路包含

Sql server 如何在WHERE子句中使用短路包含,sql-server,Sql Server,我有一个用于搜索的存储过程,其中包含几个可选参数。其中一个是@keywords,定义为 @keywords nvarchar(1000) = null, 如果@keywords为null或空字符串,我想短路,否则我需要搜索全文索引。我的逻辑过去是这样的: WHERE (@keywords IS NULL OR CONTAINS( (Title, CrossRef, company_name), @keywords)) AND -- other search terms 然而,我刚刚发现OR不

我有一个用于搜索的存储过程,其中包含几个可选参数。其中一个是@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,但我也不知道怎么做。

既然您已经在使用SP,为什么不把它放到块中来实现您的短路逻辑呢。它不仅更容易阅读,而且优化器也会更喜欢它。

以下是我最后做的事情。在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。

据我所知,我不能将WHERE子句的这一部分放在IF语句中。我必须把整个查询放进去,这意味着重复查询的其余部分。不过,这可能是最好的解决方案。您需要将查询的一个迭代放在IF块中,另一个放在ELSE块中。基本上,您必须以两种不同的方式编写查询,IF将计算@keywords的值为NULL或空。如果是,使用你的捷径逻辑。如果不是,就不要。在这两种情况下,最终都会得到一个针对该条件的定制SQL语句。