以下查询中的评估顺序是什么:
UPDATE tbl SET q = q + 1, p = q;
也就是说,"tbl"."p"
会设置为q
还是q + 1
?此处的评估顺序是否由SQL标准管理?
感谢。
在考虑Migs' answer之后,我对我能找到的所有数据库进行了一些测试。虽然我不知道标准是什么,但实施方式各不相同。
鉴于
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
Firebird 2.5改变了它的行为以匹配我测试的大多数其他SQL引擎,只留下了MySQL。相关的发行说明条目"Logic Change in SET Clause"强烈建议 根据SQL规范 的大多数行为是正确的。
我已经窃听MySQL以评论这种行为(错误编号52861),因为它们似乎是异常值。
上述错误今天(2010-05-19)已关闭,文档集已更新,以便在 UPDATE 描述和与标准的差异中显式显示此行为SQL 部分。
Bravo,MySQL。
答案 0 :(得分:13)
MySQL做“从左到右”评估并“看到”新值。 (在5.0.45-community-nt-log MySQL社区版上测试)
此外,从MySQL手册:“单表UPDATE分配通常从左到右进行评估。对于多表更新,无法保证按任何特定顺序执行分配。”
现在,鉴于评估顺序很重要,“一般”非常模糊,“不保证”非常糟糕。
所以,为了回答这个问题:IS是“SQL标准”指定的行为还是只是一种约定?
更新:掌握在“13.10 update statement:searching”项目中声明的SQL92规范“6”在更新任何T行之前,对T的每一行有效地计算(值表达式)。“
恕我直言并非绝对明确,但足以认为STANDARD不会“看到”您自己更新的结果。 考虑你的例子,Oracle,PostgreSQL和Interbase的方式。
答案 1 :(得分:6)
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
答案 2 :(得分:-1)
对表的写入必须在读取完成后正在进行的事务之后发生。