T-SQL根据输入参数的值使用不同的WHERE子句

时间:2017-07-02 21:02:33

标签: sql-server tsql

我想根据输入参数的值更改查询的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

3 个答案:

答案 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