【问题标题】:Why doesn't SQL Server fail when the result of an UPDATE is ambiguous?当 UPDATE 的结果不明确时,为什么 SQL Server 不会失败?
【发布时间】:2009-03-16 13:01:11
【问题描述】:

我有两个表,一个更新的目的地:

create table dest (value int)
insert into dest values (0)

以及来源:

create table source (value int)
insert into source values (4)
insert into source values (1)

如果我运行这个查询:

UPDATE dest SET value = (select value from source WHERE 1=1)

SQL Server 失败并显示:

Subquery returned more than 1 value. This is not permitted when 
the subquery follows =, !=, <, <= , >, >= ...

这是完美的。但是如果我运行这个查询:

UPDATE dest SET value = source.value FROM dest INNER JOIN Source ON 1=1 

...它从 source 中随机选择一个值并用它更新 dest。

可怕吗?有对此的解释吗?

【问题讨论】:

    标签: sql-server sql-server-2005 sql-server-2008


    【解决方案1】:

    是的,您的第一个查询失败的原因与更新语句无关,请运行此查询:

    select * from dest
    where value = (select value from source)
    

    当您有一个使用任何运算符(例如 =、!= 等)的子查询时...您不能返回一个以上的结果。如果您想说给我 dest 中匹配值在源中的所有值,那么您将使用 In 子句:

    select * from dest
    where value in (select value from source)
    

    至于你问题的第二部分,一个单元格只能有一个值,所以你所做的就是一遍又一遍地替换它。这是完全有效的。

    正如您所指出的,无法确定将选择哪一行,这确实很有趣,特别是考虑到如果内存服务于不同版本的 SQL 选择不同的行(旧版本我认为使用最后一行,现在他们使用第一行)。

    【讨论】:

      【解决方案2】:

      Oracle 确实禁止这样的查询:

      UPDATE dest SET value = source.value FROM dest INNER JOIN Source ON 1=1
      

      ,如果source 表不是key-preserved 表(即,您在source 的某个字段上加入dest,该字段未明确声明UNIQUE(由UNIQUE INDEXPRIMARY KEY )。

      这是一种确保在视图中最多选择dest 中的一行的方法。

      如果没有任何类型的UNIQUE 约束,更新无论如何都会失败,即使source 中没有实际的重复项。

      SQL Server 没有这个限制,只是更新到遇到的第一个值,跳过其他的。

      哪个值首先取决于几个条件,包括优化器选择的连接方法。

      【讨论】:

      • 差不多,但是一个 UNIQUE KEY 就足够了,它不必是主要的。
      【解决方案3】:

      在第一个示例中,子查询返回多行并且更新失败。在第二个示例中,连接成功,因此可以继续更新。结果是不可预测的,因为连接不受约束。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-02-12
        • 1970-01-01
        • 2020-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多