NULL 作为 WHERE 子句中的 @variable

1 null sql-server

我想将 'IS NULL' 设置为变量并在 WHERE 子句中使用它。我会将许多带有相同 WHERE 子句的表合并在一起,并希望灵活地为我的yearCompleted列使用一个变量- 请参见下面的示例 -

DECLARE @YEARCOMPLETED
SET @YEARCOMPLETED = NULL

SELECT * FROM TABLE1
WHERE yearCompleted = @YEARCOMPLETED
UNION ALL
SELECT * FROM TABLE2
WHERE yearCompleted = @YEARCOMPLETED
Run Code Online (Sandbox Code Playgroud)

在这种情况下,是否可以使用变量找到 yearCompleted 为 NULL 的行?

AMt*_*two 5

这不是最优雅的解决方案,但@YEARCOMPLETED如果它是一个值,或者如果它为空,它会返回匹配的行。这很有效,因为它能够使用yearCompleted列上的索引,但它基本上使您的代码翻倍,几乎是重复的:

DECLARE @YEARCOMPLETED smallint;
SET @YEARCOMPLETED = NULL;

SELECT * 
FROM TABLE1 
WHERE yearCompleted = @YEARCOMPLETED 
UNION ALL 
SELECT * 
FROM TABLE2 
WHERE yearCompleted = @YEARCOMPLETED
UNION ALL
SELECT * 
FROM TABLE1 
WHERE yearCompleted IS NULL
AND @YEARCOMPLETED IS NULL
UNION ALL 
SELECT * 
FROM TABLE2 
WHERE yearCompleted IS NULL
AND @YEARCOMPLETED IS NULL;
Run Code Online (Sandbox Code Playgroud)

如果您不关心 SARGability 并在该列上使用索引,则可以执行此操作。它的重复代码较少,但性能可能更差:

DECLARE @YEARCOMPLETED smallint;
SET @YEARCOMPLETED = NULL;

SELECT * 
FROM TABLE1 
WHERE COALESCE(yearCompleted,9999) = COALESCE(@YEARCOMPLETED,9999)
UNION ALL 
SELECT * 
FROM TABLE2 
WHERE COALESCE(yearCompleted,9999) = COALESCE(@YEARCOMPLETED,9999);
Run Code Online (Sandbox Code Playgroud)

为了平衡减少重复代码和良好性能,最优雅的解决方案是使用动态 SQL:

DECLARE @YEARCOMPLETED smallint;
SET @YEARCOMPLETED = NULL;

DECLARE @SQL nvarchar(Max);

SET @SQL = 'SELECT * 
FROM TABLE1
WHERE ';

IF (@YEARCOMPLETED IS NULL)
BEGIN
    SET @SQL = @SQL + ' yearCompleted IS NULL';
END
ELSE
BEGIN
    SET @SQL = @SQL + ' yearCompleted = @YEARCOMPLETED ';
END

SET @SQL = @SQL + ' UNION ALL 
SELECT * 
FROM TABLE1
WHERE ';
IF (@YEARCOMPLETED IS NULL)
BEGIN
    SET @SQL = @SQL + ' yearCompleted IS NULL';
END
ELSE
BEGIN
    SET @SQL = @SQL + ' yearCompleted = @YEARCOMPLETED';
END

EXEC sp_executesql @stmt = @SQL, @params = '@YEARCOMPLETED smallint', @YEARCOMPLETED = @YEARCOMPLETED;
Run Code Online (Sandbox Code Playgroud)