为什么 ISNULL 不能用于连接的字符串?

Why doesn't ISNULL work with concatenated strings?

我正在尝试 运行 SQL 服务器 14 中的存储过程,我需要连接一个字符串并执行它。在该字符串中,如果参数为 null,我想对列执行 select。但出于某种原因,将 ISNULL 与连接字符串一起使用不会 return 除了 'Commands completed successfully'.

之外的任何内容

我创建了一个简单的场景:

declare @startdate datetime = null;
declare @sql nvarchar(1000);

set @sql = '
select isnull('''+convert(varchar,@startdate,101)+''',''Is null'')'
exec(@sql)

而当我运行我想看到'Is null'的结果,但我只看到语句:'Command completed successfully'和当前时间(完成时间)。

有人可以告诉我为什么这不像我期望的那样工作吗?

@startdate的值为null。当您将 null 日期时间值转换为 varchar 时,您会得到(惊喜)null

我们现在获取 null varchar 并将其与其余的文字 varchar 值连接起来以分配给 @sql。猜猜看:将 null 与另一个字符串连接也会产生 null

exec() 语句的整个 @sql 的值将是 null!

这里更好的做法是使用 sq_executesql 并将您的额外数据作为自己的变量包含在内。

您没有正确传递参数。您应该使用 exec sp_executesql 来执行动态查询,并将参数及其值作为参数传递,如下所示:

考虑:

declare @sql nvarchar(1000);
set @sql = N'select isnull(convert(varchar,@startdate,101), ''Is null'')'
exec sp_executesql @sql, N'@startdate datetime', @startdate = null

请注意,这可以简化为不使用中间变量来存储参数:

exec sp_executesql 
    N'select isnull(convert(varchar,@startdate,101), ''Is null'')', 
    N'@startdate datetime', 
    @startdate = null

Demo on DB Fiddle - 两个代码块都产生 'Is null'.