我有一个带有表变量的存储过程作为输入:
CREATE TYPE [dbo].[IDArray] AS TABLE ([ID] INT NULL);
程序
CREATE PROCEDURE [dbo].[GetFiltered](
@IDs as IDArray READONLY
)
AS
SELECT * FROM A JOIN (
B JOIN @IDs ON B.BID = @IDs.ID
) ON A.AID = B.AID;
@IDs
参数用作B的过滤器。我的问题是,如果A
为空,我希望过程从@IDs
返回所有记录。我不能只进行外连接,因为这会使过滤过时。
示例数据:
Table A:
AID | Name
1 | X
2 | Y
3 | Z
Table B:
BID | AID
1 | 1
2 | 1
3 | 2
4 | 2
使用过滤器调用过程(应返回ID为1的A的值):
DECLARE @IDs IDArray;
INSERT INTO @IDs([ID]) VALUES (1)
Execute GetFiltered @IDS
调用没有过滤器的过程(应该返回A的所有值):
DECLARE @IDs IDArray;
Execute GetFiltered @IDS
答案 0 :(得分:0)
一种方法是使用exists
和not exists
:
exists
部分取代了join
和B
之间的@Ids
,
如果not exists
不包含任何行,则@ids
部分将返回所有行。
SELECT *
FROM A
JOIN B ON A.AID = B.AID
WHERE EXISTS
(
SELECT 1
FROM @IDs ids
WHERE ids.ID = B.BID
)
OR NOT EXISTS
(
SELECT 1
FROM @IDs
)
答案 1 :(得分:0)
我想我现在想出了一个答案。它可以通过左外部来解决。然后我只需要在连接表上检查null,如果没有设置过滤器,则只允许它为null。
CREATE PROCEDURE [dbo].[GetFiltered](
@IDs as IDArray READONLY
)
AS
DECLARE @Filtered bit;
IF Exists(SELECT * FROM @IDS)
SET @Filtered = 1;
ELSE
SET @Filtered = 0;
SELECT * FROM A LEFT OUTER JOIN (
B JOIN @IDs ON B.BID = @IDs.ID
) ON A.AID = B.AID
WHERE Not B.AID IS NULL OR @Filtered = 0;