[英]CASE Statement in WHERE Clause (SQL Server)
I am using Case
statement in WHERE
clause for SQL Server. 我在SQL Server的WHERE
子句中使用Case
语句。 However, the values I have in THEN
clause is a list of integer. 但是,我在THEN
子句中的值是一个整数列表。 Is there any other way of doing this in a WHERE
clause? 在WHERE
子句中还有其他方法可以这样做吗? OrderIds are in drop-down list, so either 30, 40 or 50 is selected of it none is selected, then orderID IN (30, 40, 50). OrderIds在下拉列表中,因此选择了30、40或50,但未选择任何一个,然后选择了orderID IN(30、40、50)。 PS I can't do @OrderID IS NULL otherwise it will search for every orderid in the database. PS我不能做@OrderID IS NULL,否则它将搜索数据库中的每个orderid。 So either one value or default (30,40,50) 因此,一个值或默认值(30,40,50)
WHERE
1 = 1
AND [Order].[ORDERID] IN
(CASE WHEN @ORDERID IS NOT NULL
THEN @ORDERID
ELSE
THEN ('30,40,50')
END)
I keep getting an error 我不断收到错误消息
Conversion failed when converting the varchar value '30,40,50' to data type int 将varchar值'30,40,50'转换为数据类型int时转换失败
Do not use a case
expression . 不要使用case
表达式 。 Just use basic logic: 只需使用基本逻辑:
WHERE 1 = 1 AND
(@OrderId IS NULL OR [Order].OrderId in (30, 40, 50))
I would also advise you to name your tables so they do not conflict with SQL keywords. 我还建议您为表命名,以免它们与SQL关键字冲突。 Your table could be named Orders
for instance. 例如,您的表可以命名为Orders
。
Also, I assume the string representation for the list is unnecessary. 另外,我认为列表的字符串表示形式是不必要的。 Otherwise, that introduces other issues (if you are representing a list as a string). 否则,这会带来其他问题(如果您将列表表示为字符串)。
EDIT: 编辑:
I'm worried that the actual logic you want is: 我担心您想要的实际逻辑是:
WHERE 1 = 1 AND
((@OrderId IS NULL AND [Order].OrderId in (30, 40, 50)) OR
([Order].OrderId = @OrderId)
)
This works, as long as you have a single value in @OrderId
. 只要您在@OrderId
具有单个值,此方法就@OrderId
。
CASE
expressions result in values . CASE
表达式产生值 。 You can't use them to produce expressions , such as the value list expression you're trying to use. 您不能使用它们来生成表达式 ,例如您要使用的值列表表达式。 You need to re-think how you structure this so you can just use a value. 您需要重新考虑如何构造它,以便只使用一个值。
One way to do this is to split the case expression so each possible WHEN
result is it's own condition, and the alternative result from each condition will produce true
: 一种方法是拆分case表达式,以便每个可能的WHEN
结果都是它自己的条件,并且每个条件的替代结果将产生true
:
WHERE
1 = 1
AND [Order].[ORDERID] = coalesce(@ORDERID, [Order].[ORDERID])
AND case when @orderid is null then [Order].[ORDERID] ELSE 30 end IN (30, 40, 50)
There's usually a simpler way to write the expression, but this illustrates a reliable way to make the conversion from incorrect CASE to correct WHERE. 通常有一种写表达式的简单方法,但这说明了一种可靠的方法,可以将错误的CASE转换为正确的WHERE。
If your numbers are a comma separated string of numbers , you can use this code: 如果您的数字是逗号分隔的数字字符串 ,则可以使用以下代码:
DECLARE @LIST VARCHAR(200)
SET @LIST = '30, 40, 50'
---------------------------
WHERE 1 = 1 AND
(
@OrderId IS NULL
OR
[Order].OrderId in (SELECT * FROM dbo.SplitStrings_Moden(@LIST,N','))
)
To use the above code you need to define the following function in your DB to get a Table from comma separated string of numbers: 要使用上面的代码,您需要在数据库中定义以下函数,以逗号分隔的数字字符串获取表格:
CREATE FUNCTION dbo.SplitStrings_Moden
(
@List NVARCHAR(MAX),
@Delimiter NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING AS
RETURN
WITH E1(N) AS ( SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1),
E2(N) AS (SELECT 1 FROM E1 a, E1 b),
E4(N) AS (SELECT 1 FROM E2 a, E2 b),
E42(N) AS (SELECT 1 FROM E4 a, E2 b),
cteTally(N) AS (SELECT 0 UNION ALL SELECT TOP (DATALENGTH(ISNULL(@List,1)))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E42),
cteStart(N1) AS (SELECT t.N+1 FROM cteTally t
WHERE (SUBSTRING(@List,t.N,1) = @Delimiter OR t.N = 0))
SELECT Item = SUBSTRING(@List, s.N1, ISNULL(NULLIF(CHARINDEX(@Delimiter,@List,s.N1),0)-s.N1,8000))
FROM cteStart s;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.