我正在编写一个“简单”的SQL函数来选择数据,具体取决于WHERE
子句中的参数:
DECLARE @csp AS CHAR(1) = 'F'
SELECT [NUMERO_DOSSIER]
FROM [dbo].[Dossier]
WHERE
[CSP] IN
(
CASE @csp
WHEN 'F' THEN
(SELECT [CSP] FROM [dbo].[CSP_1])
WHEN 'N' THEN
(SELECT [CSP] FROM [dbo].[CSP_2])
END
)
根据SQL Server 2012,此查询没有语法错误。但运行它会返回此错误:
Msg 512,Level 16,State 1,Line 2子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。
根据我的理解,这里的问题是:CASE
函数返回标量,并且不能返回表。
如何重写它以使其有效?
答案 0 :(得分:2)
不要在CASE
子句中使用WHERE
- 它通常会使逻辑更复杂。只需将逻辑扩展为布尔逻辑:
WHERE ( @csp = 'F' AND [CSP] IN (SELECT [CSP] FROM [dbo].[CSP_1]) ) OR
( @csp = 'N' AND [CSP] IN (SELECT [CSP] FROM [dbo].[CSP_2]) )
答案 1 :(得分:2)
一种方法是使用UNION ALL
子查询:
SELECT [NUMERO_DOSSIER]
FROM [dbo].[Dossier]
WHERE
[CSP] IN
(
SELECT [CSP]
FROM [dbo].[CSP_1]
WHERE @csp = 'F'
UNION ALL
SELECT [CSP]
FROM [dbo].[CSP_2]
WHERE @csp = 'N'
);
答案 2 :(得分:1)
使用两个CTE
和两个JOIN
操作:
DECLARE @csp AS CHAR(1) = 'F'
;WITH Table1 AS (
SELECT [CSP]
FROM [dbo].[CSP_1]
), Table2 AS (
SELECT [CSP]
FROM [dbo].[CSP_2]
)
SELECT [NUMERO_DOSSIER]
FROM [dbo].[Dossier] AS d
JOIN Table1 AS t1 ON @csp = 'F' AND d.CSP = t1.CSP
JOIN Table2 AS t2 ON @csp = 'N' AND d.CSP = t2.CSP
修改强>
看到@ Dan的回答后,这可能更干净了:
;WITH Table1 AS (
SELECT [CSP]
FROM [dbo].[CSP_1]
WHERE @csp = 'F'
), Table2 AS (
SELECT [CSP]
FROM [dbo].[CSP_2]
WHERE @csp = 'N'
)
SELECT [NUMERO_DOSSIER]
FROM [dbo].[Dossier] AS d
JOIN Table1 AS t1 ON d.CSP = t1.CSP
JOIN Table2 AS t2 ON d.CSP = t2.CSP