在动态SQL Server查询中,我想基于其他表构建动态插入脚本。
SELECT 'INSERT INTO MyTable(column) VALUES ' + Concat ('(',ISNULL(''''+ ColumnValue+'''', 'NULL'), ')' ) from myOriginalTable
,并且如果原始表中的列值为空,我希望它返回NULL作为varchar值。
但是,当列值为空时:
(基本上在SSMS中):select ISNULL(''''+ NULL+'''', 'NULL')
然后返回的值是'NUL'varchar而不是NULL,而且我不知道为什么。
当我尝试查询超出动态上下文时,它会起作用:
select isnull(NULL,'NULL')
这是功能还是错误?
这与表定义无关,要重现此问题,只需在SSMS中运行select ISNULL(''''+ NULL+'''', 'NULL')
或从在线平台中找到result
答案 0 :(得分:2)
与COALESCE
1 相比,您通常更喜欢ISNULL
的众多原因之一。
select COALESCE(''''+ NULL+'''', 'NULL')
如您所述,与NULL
相同时返回ISNULL
。返回NUL
。
为什么?因为ISNULL
不使用SQL Server其他地方使用的data type precedence的常规规则,而是强制结果具有与第一个参数相同的数据类型,对于上面的参数显然一种[n][var]char(3)
类型。
另一方面,COALESCE
考虑其参数 all 的类型(更喜欢它的另一个原因-推广到两个以上的参数)来确定其参数的适当数据类型结果。由于'NULL'
是char(4)
文字,因此结果数据类型必须能够容纳至少4个字符。
1 我过去唯一使用ISNULL
的地方是视图中计算列/表达式的定义,其中数据库引擎用来分析ISNULL
和{ {1}}有所不同,我希望它计算得出的数据类型为COALESCE
。不知道这种差异是否仍然存在。
答案 1 :(得分:1)
因为
您的表中有一行,其中ColumnValue
包含文字字符串'NUL'
动态查询生成的第一行的宽度不超过3个字符,因此引擎推论它应该输出varchar(3)
列。然后'NULL'
被截断为'NUL'
特别是,如果查询的第一行是ColumnValue
为空的那一行,则表达式ISNULL(''''+ NULL+'''', 'NULL')
的类型将被评估为''''+ NULL+''''
第二种情况,您应该可以通过类似的方式解决
Concat ('(', ISNULL(Cast(''''+ Null +'''' as VarChar(4)), 'NULL'), ')' )