在 SQL Server 更新语句中使用相关子查询会产生意外结果

发布于 2025-01-02 11:51:30 字数 380 浏览 0 评论 0原文

我正在向还没有主键列的表引入主键列。添加默认值为 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 字段?

I'm introducing a primary key column to a table that doesn't have one yet. After I have added a normal field Id (int) with a default value of 0 I tried using the following update statement to create unique values for each record:

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

I would expect the subquery to be executed for each row because I'm referencing t1. Each time the subquery would be executed the count should be one less but it doesn't work.

The result is that Id is still 0 in every record. I have used this before on other DBMS with success. I'm using SQL Server 2008 here.

How do I generate unique values for each record and update the Id field?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

沫离伤花 2025-01-09 11:51:30

尝试解释为什么它没有按您的预期工作

我希望对每一行执行子查询,因为我引用了 t1。

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

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

您期望通过对每行子查询进行一次评估来执行 UPDATE。但它是首先对所有受影响的行进行评估的一条语句,然后更改(更新)这些行。 (DBMS 可能会以其他方式执行此操作,但结果应该就像它是这样做的)。

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

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

我之前曾在其他 DBMS 上成功使用过此方法。

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

我在这里使用 SQL Server 2008。

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

Trying to explain why it doesn't work as you expect:

I would expect the subquery to be executed for each row because I'm referencing t1.

It is executed and it can affect all rows. But an UPDATE stetement is one statement and it is executed as one statement that affects a whole table (or a part of it if you have a WHERE clause).

Each time the subquery would be executed the count should be one less but it doesn't work.

You are expecting the UPDATE to be executed with one evaluation of the subquery per row. But it is one statement that is first evaluated - for all affected rows - and then the rows are changed (updated). (A DBMS may do it otherwise but the result should be nonetheless as if it was doing it this way).

The result is that Id is still 0 in every record.

That's the correct and expected behaviour of this statement when all rows have the same 0 value before execution. The COUNT(*) is 0.

I have used this before on other DBMS with success.

My "wild" guess is that you have used it in MySQL. (Correction/Update: my guess was wrong, this syntax for Update is not valid for MySQL, apparently the query was working "correctly" in Firebird). The UPDATE does not work in the standard way in that DBMS. It works - as you have learned - row by row, not with the full table.

I'm using SQL Server 2008 here.

This DBMS works correctly with UPDATE. You can write a different Update statement that would have the wanted results or, even better, use an autogenerated IDENTITY column, as others have advised.

剩余の解释 2025-01-09 11:51:30

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

尝试在此处查看此答案:

向现有列添加身份

The SQL is updating every row with the number of records where the ID doesn't equal 0. As all the rows ID equal 0 then there are no rows that are not equal to 0, and hence nothing gets updated.

Try looking at this answer here:

Adding an identity to an existing column

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文