在 WHERE 子句中使用 CASE 来评估空参数
Using of CASE in WHERE clause to evaluate empty parameters
有没有更好的获取方式?
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='') 或 return 值的子集 (@Desc='test'),这允许 return 所有值。
使用 OR 运算符代替大小写
DECLARE @Desc VARCHAR(200) = ''
SELECT [id],
[Desc],
[Col1],
[Col2]
FROM [dbo].[tbl]
WHERE
(
ISNULL(@Desc,'')=''
)
OR
(
ISNULL(@Desc,'')<>''
AND
[Desc] LIKE '%'+ @Desc +'%'
)
使用两种逻辑的执行计划差异
使用案例
使用或
执行引擎最好在查询之前做尽可能多的参数处理。
DECLARE @Desc VARCHAR(200) = '';
DECLARE @SelectAll bit;
SET @SelectAll = CASE WHEN @Desc = '' THEN 1 ELSE 0 END;
SET @Desc = CASE WHEN @Desc = '' THEN @Desc ELSE ('%' + @Desc + '%') END;
SELECT [id],
[Desc],
[Col1],
[Col2]
FROM [dbo].[tbl]
WHERE
(@SelectAll = 1)
OR
(@SelectAll = 0 AND [Desc] LIKE @Desc);
如果您不介意代码重复,您可以更进一步,通过 IF / ELSE 拆分两个单独的查询。
如果您使用 null 可以节省一些步骤
declare @userId int = null;
SELECT TOP 1000 [AuctionId]
,[UserId]
,[BiddingPrice]
,[DateTime]
FROM [Test].[dbo].[Bid]
WHERE isnull(@userId, [UserId]) = [UserId];
好吧,正如 Aaron Bertrand 评论的那样,您当前的查询可以简单地写成这样:
DECLARE @Desc VARCHAR(200) = ''
SELECT [id],
[Desc],
[Col1],
[Col2]
FROM [dbo].[tbl]
WHERE [Desc] LIKE '%'+ @Desc +'%'
因为如果 @Desc
包含一个空字符串,结果将是 [Desc] LIKE '%%'
- 所以所有 [Desc]
不为 null 的记录无论如何都会被 returned。
如果@Desc
可以作为null
传递,使用Coalesce
将null
转换为空字符串:
...WHERE [Desc] LIKE '%'+ COALESCE(@Desc, '') +'%'
请注意,在这两个问题中,Desc
列包含 null
的记录将不会被 return 编辑。如果这是一个可为空的列,并且您还想 return 记录 null
并且 @Desc
参数也为 null 或空,那么您应该使用 OR
:
SELECT [id],
[Desc],
[Col1],
[Col2]
FROM [dbo].[tbl]
WHERE [Desc] LIKE '%'+ @Desc +'%'
OR (COALESCE(@Desc, '') = '' AND [Desc] IS NULL)
此外,请注意,这只是因为您使用了 LIKE
- 如果您尝试使用不同的运算符(例如 =
、<
、>
etc') 你应该像其他答案一样使用 OR
语法。
有没有更好的获取方式?
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='') 或 return 值的子集 (@Desc='test'),这允许 return 所有值。
使用 OR 运算符代替大小写
DECLARE @Desc VARCHAR(200) = ''
SELECT [id],
[Desc],
[Col1],
[Col2]
FROM [dbo].[tbl]
WHERE
(
ISNULL(@Desc,'')=''
)
OR
(
ISNULL(@Desc,'')<>''
AND
[Desc] LIKE '%'+ @Desc +'%'
)
使用两种逻辑的执行计划差异
使用案例
使用或
执行引擎最好在查询之前做尽可能多的参数处理。
DECLARE @Desc VARCHAR(200) = '';
DECLARE @SelectAll bit;
SET @SelectAll = CASE WHEN @Desc = '' THEN 1 ELSE 0 END;
SET @Desc = CASE WHEN @Desc = '' THEN @Desc ELSE ('%' + @Desc + '%') END;
SELECT [id],
[Desc],
[Col1],
[Col2]
FROM [dbo].[tbl]
WHERE
(@SelectAll = 1)
OR
(@SelectAll = 0 AND [Desc] LIKE @Desc);
如果您不介意代码重复,您可以更进一步,通过 IF / ELSE 拆分两个单独的查询。
如果您使用 null 可以节省一些步骤
declare @userId int = null;
SELECT TOP 1000 [AuctionId]
,[UserId]
,[BiddingPrice]
,[DateTime]
FROM [Test].[dbo].[Bid]
WHERE isnull(@userId, [UserId]) = [UserId];
好吧,正如 Aaron Bertrand 评论的那样,您当前的查询可以简单地写成这样:
DECLARE @Desc VARCHAR(200) = ''
SELECT [id],
[Desc],
[Col1],
[Col2]
FROM [dbo].[tbl]
WHERE [Desc] LIKE '%'+ @Desc +'%'
因为如果 @Desc
包含一个空字符串,结果将是 [Desc] LIKE '%%'
- 所以所有 [Desc]
不为 null 的记录无论如何都会被 returned。
如果@Desc
可以作为null
传递,使用Coalesce
将null
转换为空字符串:
...WHERE [Desc] LIKE '%'+ COALESCE(@Desc, '') +'%'
请注意,在这两个问题中,Desc
列包含 null
的记录将不会被 return 编辑。如果这是一个可为空的列,并且您还想 return 记录 null
并且 @Desc
参数也为 null 或空,那么您应该使用 OR
:
SELECT [id],
[Desc],
[Col1],
[Col2]
FROM [dbo].[tbl]
WHERE [Desc] LIKE '%'+ @Desc +'%'
OR (COALESCE(@Desc, '') = '' AND [Desc] IS NULL)
此外,请注意,这只是因为您使用了 LIKE
- 如果您尝试使用不同的运算符(例如 =
、<
、>
etc') 你应该像其他答案一样使用 OR
语法。