在WHERE子句中使用CASE来评估空参数

时间:2018-01-05 15:21:06

标签: sql sql-server tsql case sql-like

有没有更好的方法来获得以下内容?

DECLARE @Desc VARCHAR(200) = ''

SELECT [id],
       [Desc],
       [Col1],
       [Col2]
FROM [dbo].[tbl]
WHERE [Desc] LIKE CASE
                WHEN @Desc LIKE ''
                     THEN [Desc]
                     ELSE '%'+ @Desc +'%'
                END

如果未定义参数(@Desc ='')或返回值的子集(@Desc =' test'),则允许返回所有值。

4 个答案:

答案 0 :(得分:3)

使用OR运算符代替Case

DECLARE @Desc VARCHAR(200) = ''

SELECT [id],
       [Desc],
       [Col1],
       [Col2]
FROM [dbo].[tbl]
WHERE 
    (
        ISNULL(@Desc,'')=''
    )
    OR
    (
        ISNULL(@Desc,'')<>''
        AND
        [Desc] LIKE '%'+ @Desc +'%'
    )

使用两种逻辑的执行计划差异

使用案例

enter image description here

使用或

enter image description here

答案 1 :(得分:2)

执行引擎在查询之前执行尽可能多的参数处理会更好。

replace into people_old select * from people;

如果您不介意代码重复,您可以更进一步,并按IF / ELSE分割两个单独的查询。

答案 2 :(得分:1)

如果使用null,则保存一些步骤

declare @userId  int = null; 

SELECT TOP 1000 [AuctionId]
      ,[UserId]
      ,[BiddingPrice]
      ,[DateTime]
  FROM [Test].[dbo].[Bid] 
  WHERE isnull(@userId, [UserId]) = [UserId];

答案 3 :(得分:1)

好吧,正如Aaron Bertrand评论的那样,您当前的查询可以简单地写成:

DECLARE @Desc VARCHAR(200) = ''

SELECT [id],
       [Desc],
       [Col1],
       [Col2]
FROM [dbo].[tbl]
WHERE [Desc] LIKE '%'+ @Desc +'%' 

由于@Desc包含空字符串,因此[Desc] LIKE '%%'将生成{ - 所有[Desc]未归零的记录。

如果@Desc可以null传递,请使用Coalescenull转换为空字符串:

...WHERE [Desc] LIKE '%'+ COALESCE(@Desc, '') +'%' 

请注意,在这两个问题中,不会返回Desc列包含null的记录。如果这是一个可以为空的列,并且您还要将记录返回到null并且@Desc参数也为空或空,那么您应该使用OR

SELECT [id],
       [Desc],
       [Col1],
       [Col2]
FROM [dbo].[tbl]
WHERE [Desc] LIKE '%'+ @Desc +'%' 
OR (COALESCE(@Desc, '') = '' AND [Desc] IS NULL)

此外,请注意,这只是因为您使用了LIKE - 您是否应该尝试使用其他运算符(例如=<,{{1}来评估条件你应该像其他答案一样使用>语法。