我想根据输入参数的值更改查询的WHERE
子句。我猜这是可能的,但似乎我以错误的方式接近它?
我的SP查询的简化版本:
CREATE PROCEDURE [dbo].[GetMailboxMessagesByStatus]
@UserId UNIQUEIDENTIFIER,
@MessageStatus INT
AS
BEGIN
SELECT *
FROM MailboxMessages m
WHERE
CASE @MessageStatus
WHEN 4 THEN m.SenderId = @UserId --Sent
ELSE m.RecipientId = @UserId --Inbox
END
END
GO
答案 0 :(得分:9)
不需要case或iif构造:
WHERE @MessageStatus = 4 AND m.SenderId = @UserId
OR @MessageStatus <> 4 AND m.RecipientId = @UserId
编辑: 当被查询的表非常大时,请注意使用此构造的大表。使用像Chester Lim这样的IF语句使用2个单独的查询可能是更好的解决方案。 Preventing parameter sniffing也许是一个好主意
答案 1 :(得分:2)
您可以将WHERE子句更改为
WHERE (CASE WHEN @MessageStatus = 4 THEN m.SenderId ELSE m.RecipientId END) = @UserId
因为你在CASE中的THEN之后放的东西应该是一个值,而不是一个比较。
或使用IIF代替CASE:
WHERE IIF(@MessageStatus = 4,m.SenderId,m.RecipientId) = @UserId
但是如果您使用IF ... ELSE ...并且基于@MessageStatus运行不同的Query,则SQL将运行更高效。
正在为此写一个例子,但是Chester Lim已经打败了我。 ;)
(所以在这个答案中不需要重复这种方法)
答案 2 :(得分:2)
使用IF语句。
CREATE PROCEDURE [dbo].[GetMailboxMessagesByStatus]
@UserId UNIQUEIDENTIFIER ,
@MessageStatus INT
AS
BEGIN
IF ( @MessageStatus = 4 )
BEGIN
SELECT *
FROM MailboxMessages
WHERE m.SenderId = @UserId; --Sent
END;
ELSE
BEGIN
SELECT *
FROM MailboxMessages m
WHERE m.RecipientId = @UserId; --Inbox
END;
END;
GO
编辑 - 由LukStorms提供的更好的方式(因为我直到看到他的回答才知道IIF)
CREATE PROCEDURE [dbo].[GetMailboxMessagesByStatus]
@UserId UNIQUEIDENTIFIER ,
@MessageStatus INT
AS
BEGIN
SELECT *
FROM MailboxMessages m
WHERE IIF (@MessageStatus = 4, m.SenderId, m.RecipientId) = @UserId; --Sent
END
GO