I would like to change the WHERE
clause of a query based upon the value of an input parameter. I'm guessing this is possible, but it seems that I'm approaching it in the wrong way?
A simplified version on my SP query:
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
You can specify multiple conditions in a single WHERE clause to, say, retrieve rows based on the values in multiple columns. You can use the AND and OR operators to combine two or more conditions into a compound condition. AND, OR, and a third operator, NOT, are logical operators.
Solution 1. You can use parameters in a WITH clause just like in a traditional statement. The problem in the example is the IN operator which requires a list of values.
You can't use a variable in an IN clause - you need to use dynamic SQL, or use a function (TSQL or CLR) to convert the list of values into a table.
The IN operator allows you to specify multiple values in a WHERE clause. The IN operator is a shorthand for multiple OR conditions.
No need for case or iif constructs:
WHERE @MessageStatus = 4 AND m.SenderId = @UserId
OR @MessageStatus <> 4 AND m.RecipientId = @UserId
EDIT: Be aware on big tables using this construct when the table being queried is quite large. Using 2 seperate queries using a IF statement like Chester Lim suggested might be the better solution. Preventing parameter sniffing might also be a good idea
Use an IF statement.
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
EDIT - a much better way provided by LukStorms (since i did not know IIF until i saw his answer)
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
You could change that WHERE clause to
WHERE (CASE WHEN @MessageStatus = 4 THEN m.SenderId ELSE m.RecipientId END) = @UserId
Because what you put after the THEN in a CASE should just be a value, not a comparison.
Or use IIF instead of a CASE:
WHERE IIF(@MessageStatus = 4,m.SenderId,m.RecipientId) = @UserId
But the SQL will run more efficient if you use an IF ... ELSE ... and run a different Query based on the @MessageStatus.
Was writing an example for that, but Chester Lim already beat me to it. ;)
(so no need to repeat that approach in this answer)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With