如何在 sql 服务器的动态查询中检查 IS NULL

How to check IS NULL in dynamic query in sql server

我使用动态查询做了以下存储过程,请参见以下代码蓝图

ALTER PROCEDURE [dbo].[usp_Report] (
 @LocationId INT = NULL
,@UserId INT = NULL)

声明@miscquery NVARCHAR (MAX); 开始 SET @miscquery='

                       SELECT 
                        ,A.AgreementNumber AS Contract
                        ,A.AgreementId
                        
                    FROM tblAgreement A
                    
                    WHERE 
                    AND (A.IsDeleted = 0 or A.IsDeleted is null)
                    AND (
                                (
                                    ' + convert(NVARCHAR(30), @LocationId) + ' IS NULL  
                                    AND (
                                    A.CheckoutLocation IN (
                                        SELECT LocationId
                                        FROM [dbo].[tblUserLocations]
                                        WHERE UserID = ' + convert(VARCHAR(10), @userId) +' 
                                            AND IsDeleted = 0
                                        )
                                    OR A.CheckoutLocation IS NULL
                                    )
                                )
                                OR A.CheckoutLocation =   ' + convert(VARCHAR(10), @LocationId) +' 
                        )'
    
                    
    
                EXEC (@miscquery)
end
)

这里,当我使用 @Locationid 为 null 执行查询时,结果不是 return table,它 return 如下所示

(63 行受影响)

(2325 行受影响)

请帮帮我。谢谢

您拥有的代码不可能是您的实际代码,首先是因为在开始时您尝试在声明它之前设置一个名为 @miscquery 的变量。这段代码也没有理由是动态的,所以很明显你也在做一些其他的事情。

出于某种原因,我认为您“需要”动态 SQL。我将放入有关清理您的输入的标准警告。就是这样。

好的。即使声明了 @miscquery,编写的代码也不会产生任何结果。根据您对 concat_null_yields_null.

的设置,它要么抛出语法错误,要么什么都不做。

让我们以可能的情况为例:您对此有默认设置,这意味着当您将 varchar 连接到 null 时,结果是 null.

遵守以下代码:

declare @locationId int = null;
select 'this sentence ends with...' + convert(nvarchar(30), @locationId);

输出结果是什么?

  1. “这句话结尾是……null”
  2. “这句话以...结尾”
  3. null

答案是 3。请注意:这不是值为“null”的字符串。那只是 null。当您将 convertnull 值赋给一个字符串时,您不会得到值为“null”的字符串,您会得到 null 值。

好的,现在我们尝试将 null 添加到字符串的末尾。当您尝试使用 + 运算符将 null 值连接到字符串时,整个结果为 null.

因此,您的整个 @miscquery 变量在赋值结束时是 null

所以你现在所做的与此相同:

declare @myquery varchar(max) = null;
exec sp_executesql @myquery

这是有效的,不会抛出任何错误,但什么也不做。然后你的代码的其余部分做它做的任何事情,并产生你看到的结果。

如果 concat_null_yields_null 被设置为关闭那么你会得到一个语法错误,因为当你把它交给 sp_executesql.[=36 时生成的文本将是无效的 SQL =]

正如 Dan 所说,最好和最安全的解决方案是参数化您的输入。但撇开这些不谈,您需要的解决方案如下所示。在 iif() 函数中,我查看 @locationId 的值。如果它是 null,那么我想要字符串“null”。如果它不是 null,那么我想要它具有的任何值的字符串转换。

declare @locationId int = null;

declare @query varchar(max) = 
   'select * from mytable where ' 
    + iif(@locationId is null, 'null', convert(nvarchar(30), @locationId)) 
    + ' is null';

print @query;