【问题标题】:Using correlated subquery in SQL Server update statement gives unexpected result在 SQL Server 更新语句中使用相关子查询会产生意外结果
【发布时间】:2012-02-06 14:07:46
【问题描述】:

我正在向一个还没有主键列的表引入一个主键列。添加默认值为 0 的普通字段 Id (int) 后,我尝试使用以下更新语句为每条记录创建唯一值:

update t1
set t1.id = (select count(*) from mytable t2 where t2.id <> t1.id)
from mytable t1

我希望对每一行都执行子查询,因为我引用的是t1。每次执行子查询时,计数应该少一,但它不起作用。

结果是每条记录的Id仍然为0。我以前在其他 DBMS 上成功使用过它。我在这里使用的是 SQL Server 2008。

如何为每条记录生成唯一值并更新 Id 字段?

【问题讨论】:

  • 你为什么不只是添加一个ID INT IDENTITY(1,1) 列?然后 SQL Server 将自动为ID 创建唯一值,您根本不需要更新任何内容.....
  • 谢谢。我会尽力。我使用许多不同的 DBMS,所以我总是尝试最通用的方法。

标签: sql sql-server correlated-subquery


【解决方案1】:

试图解释为什么它没有像你期望的那样工作

我希望对每一行都执行子查询,因为我引用的是 t1.

它被执行并且可以影响所有行。但是UPDATE 语句是一个语句,它作为一个影响整个表的语句执行(或者如果你有一个WHERE 子句,它的一部分)。

每次执行子查询时,计数应该减一,但它不起作用。

您期望UPDATE 执行时每行对子查询进行一次评估。但它是首先评估的一条语句 - 对于所有受影响的行 - 然后更改(更新)行。 (DBMS 可能会这样做,但结果应该是好像它正在这样做)。

结果是每条记录的Id仍然为0。

当所有行在执行前具有相同的0 值时,这是该语句的正确和预期行为。 COUNT(*)0

我之前在其他 DBMS 上成功使用过这个。

我的“疯狂”猜测是您在 MySQL 中使用过它。 (更正/更新:我的猜测是错误的,更新的这种语法对 MySQL 无效,显然查询在 Firebird 中“正常”工作)。 UPDATE 在该 DBMS 中不能以标准方式工作。正如您所了解的那样,它可以逐行工作,而不是整个表格。

我在这里使用的是 SQL Server 2008。

此 DBMS 与 UPDATE 一起正常工作。您可以编写一个不同的 Update 语句来获得想要的结果,或者更好地使用自动生成的 IDENTITY 列,正如其他人所建议的那样。

【讨论】:

  • 感谢您的详细回复。我期待像你说的那样逐行行为(也在 Firebird DBMS 中)。
  • 您的帐户听起来非常合理 :) 但我不得不问:mySQL 中的相同更新是否真的像 OP 预期的那样工作?只是这不是 SQL 应该如何工作的!
  • 你说得对。我不知道 MySQL 在这种情况下的行为。
  • 查询不像在 MySQL 中那样工作(我错了)。语法不同 (UPDATE ... FROM ... SET ...),您不能将同一个表同时指定为 Update 的目标和 WHERE 子句内。
  • @onedaywhen:此查询在 MySQL 中不起作用。但是 MySQL 的 UPDATE 以非标准方式工作。例如,如果 id 是唯一键或主键,则不能执行 UPDATE t SET id = id+1(您将收到重复的主键错误)。但是,您可以这样做:UPDATE t SET id = id+1 ORDER BY id DESC(这种方式没有重复,这清楚地表明行已更新并且约束逐行检查!)
【解决方案2】:

SQL 使用 ID 不等于 0 的记录数更新每一行。由于所有行 ID 都等于 0,因此没有不等于 0 的行,因此不会更新任何内容。

尝试在此处查看此答案:

Adding an identity to an existing column

【讨论】:

  • 我使用这个脚本来更新 Id 字段:DECLARE count INT SET count = (SELECT COUNT(*) FROM MYTABLE WHERE ID = 0) WHILE (count &gt; 0) BEGIN UPDATE TOP (1) MYTABLE SET ID=@count WHERE ID=0 SET count = (SELECT COUNT(*) FROM MYTABLE WHERE ID = 0) END
猜你喜欢
  • 1970-01-01
  • 2014-08-16
  • 1970-01-01
  • 2020-09-03
  • 2014-08-27
  • 2018-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多