SQLServer更新语句对空值扼流,即使使用isNull()

Jer*_*zak 4 sql sql-server isnull

请注意,我已经更改了表格和字段的名称,以使其简短易懂.

我有一个问题,归结为,来到这个:

update destTable 
set destField = ( select top 1 isnull(s.sourceField, '') from sourceTable s 
where <various matches between the destTable table and the s table>
);
Run Code Online (Sandbox Code Playgroud)

(我知道语法'更新destTable设置destField ...来自destTable d,sourceTable s ......'但是我不知道如何将"top 1"放入其中.)

从这里我得到SQLServer 2012 Express结果:

Msg 515, Level 16, State 2, Line 1
Cannot insert the value NULL into column 'destField', table 'destTable'; column does not allow nulls. UPDATE fails.
The statement has been terminated.
Run Code Online (Sandbox Code Playgroud)

对于这两个表,所有字段都定义为非null和default('').

"前1"很重要,因为sourceTable可能有多个匹配"where"子句.

我查询了sourceTable的所有行,发现它的所有sourceField值都是非null.然而,我得到了结果.

查询的本质是,在1000个destTable记录中,与sourceTable的匹配将仅产生300行的匹配.其他700个destTable记录将没有匹配项.

我不明白SQLServer对我做了什么.当我上次使用MySQL运行它时,此查询工作正常.

谢谢你,杰罗姆.

Gor*_*off 7

问题是查询没有返回任何行...因此产生一个NULL值.移动isNULL()子查询外部:

update destTable 
set destField =  isnull((select top 1 s.sourceField
                         from sourceTable s 
                         where <various matches between the destTable table and the s table>
                        ), '');
Run Code Online (Sandbox Code Playgroud)

顺便说一下,通常我会coalesce()在这种情况下提倡,因为它是标准.然而,正如Aaron Bertrand 在这里描述的那样,两者表现不同.特别是,第一个参数似乎被评估了两次,当它是一个子查询时非常昂贵. Isnull()显然,没有这个问题.