4

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

我有一个查询,归结为:

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

(我知道语法'update destTable set destField ... from 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.

对于这两个表,所有字段都定义为非空和默认 ('')。

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

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

查询的本质是,在 1000 条 destTable 记录中,与 sourceTable 的匹配将产生仅 300 行的匹配。其他 700 条 destTable 记录将不匹配。

我不明白 SQLServer 对我做了什么。当我上次使用 MySQL 运行它时,这个查询工作得很好。

在此先感谢,杰罗姆。

4

1 回答 1

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>
                        ), '');

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

于 2013-07-22T13:15:15.860 回答