42

以下查询中的评估顺序是什么:

UPDATE tbl SET q = q + 1, p = q;

也就是说,将"tbl"."p"设置为qor q + 1? 这里的评估顺序是否受 SQL 标准的约束?

谢谢。

更新

在考虑了Migs 的回答后,我对我能找到的所有数据库进行了一些测试。虽然我不知道标准是怎么说的,但实现会有所不同。

给定

CREATE TABLE tbl (p INT NOT NULL, q INT NOT NULL);
INSERT INTO tbl VALUES (1, 5);   -- p := 1, q := 5
UPDATE tbl SET q = q + 1, p = q;

我发现 和 的值"p""q"

database           p   q
-----------------+---+---
Firebird 2.1.3   | 6 | 6  -- But see "Update 2" below
InterBase 2009   | 5 | 6
MySQL 5.0.77     | 6 | 6  -- See "Update 3" below
Oracle XE (10g)  | 5 | 6
PostgreSQL 8.4.2 | 5 | 6
SQLite 3.3.6     | 5 | 6
SQL Server 2016  | 5 | 6

更新 2

Firebird 2.5 改变了它的行为以匹配我测试过的大多数其他 SQL 引擎,只留下 MySQL。相关的发行说明条目“SET 子句中的逻辑更改”强烈建议根据 SQL 规范大多数行为是正确的

我已经窃听 MySQL 来评论这种行为(错误号52861),因为它们似乎是异常值。

更新 3

上述错误已于今天 (2010-05-19) 关闭,并且将更新文档以在UPDATE描述和与标准 SQL 的差异部分中明确说明此行为。

布拉沃,MySQL。

4

3 回答 3

14

MySQL 进行“从左到右”评估并“看到”新值。(在 5.0.45-community-nt-log MySQL 社区版上测试)

此外,来自 MySQL 手册:“单表 UPDATE 分配通常从左到右进行评估。对于多表更新,不能保证以任何特定顺序执行分配。”

现在,“一般”是相当模糊的,“不保证”是非常糟糕的,因为评估的顺序很重要。

那么,为了回答这个问题:行为是由“SQL 标准”指定的还是只是一种约定?


更新:掌握了 SQL92 规范,该规范在“13.10 更新语句:搜索”项“6)在更新 T 的任何行之前有效地评估了 T 的每一行(值表达式)。”

恕我直言,并非绝对明确,但足以考虑标准不是“看到”您自己更新的结果。考虑到您的示例,Oracle、PostgreSQL 和 Interbase 的做法。

于 2010-04-13T20:06:02.640 回答
7

UPDATE没有看到其工作的结果。

p将设置q为更新前的。

以下代码将只交换列:

DECLARE @test TABLE (p INT, q INT)

INSERT
INTO    @test
VALUES  (2, 3)

SELECT  *
FROM    @test

p    q
---  ---
  2    3

UPDATE  @test
SET     p = q,
        q = p

SELECT  *
FROM    @test

p    q
---  ---
  3    2
于 2010-02-04T21:07:07.557 回答
-1

对表的写入必须发生在读取完成时正在进行的事务之后。

于 2010-02-04T21:05:33.960 回答