用其他列的值更新列,该列本身在同一UPDATE中更新

时间:2018-11-07 11:43:39

标签: mysql sql postgresql

考虑此UPDATE语句:

UPDATE tbl_book 
SET return_date = planned_return_date, 
    planned_return_date = null 
WHERE book_id = 12;

我想此更新的工作方式如下:

  1. 在表 tbl_book 中找到ID匹配的记录,并设置值
  2. 返回日期等于 planned_return_date
  3. 的值
  4. 然后,,将planned_return_date的值设置为NULL

我的假设正确吗? SET-Clauses的顺序重要吗? 我什至猜测,分配中的列引用将始终反映“旧”记录的值,对吗?在这种情况下,排序无所谓...

编辑2018-11-08:为了澄清,我用mysql和postgresql标记了我的查询,因为我需要知道两者的答案。

3 个答案:

答案 0 :(得分:4)

根据SQL标准,不应在任何这些表达式中使用更新后的值。 2003规范 1 中的相关文本指出:

  

在更新T的任何行之前,已针对T的每一行有效地评估了每个<update source>的{​​{1}}。

<set clause>子句中<update source>子句中每个赋值运算符右边的部分。

似乎MySQL可能未遵循此处的标准,但我相信PostgreSQL和大多数其他数据库产品会遵循。对于MySQL,这是documented

  

以下语句中的第二个赋值将SET设置为当前(更新)的col2值,而不是原始的col1值。结果是col1col1具有相同的值。 此行为不同于标准SQL。

col2

(我的重点


1 第14.11节UPDATE t1 SET col1 = col1 + 1, col2 = col1; 。 2003标准的选择是任意的,我不认为这在标准的版本之间会有太大变化。

答案 1 :(得分:3)

您的查询是:

UPDATE tbl_book 
    SET return_date = planned_return_date, 
        planned_return_date = null 
    WHERE book_id = 12;

进行update时,请将该表视为每个记录有两个版本-我们将其称为“旧”和“新”,因为这是触发器中常用的术语。

new 记录中的值为set=另一侧的值来自 old 记录。

答案 2 :(得分:2)

SET-Clauses的顺序重要吗?是的,顺序是一个问题(对于mysql),这是因为如果您在下面的查询中执行

create table t 
(
id int, id1 int, id2 int
);
insert into t 
values 
(1,2,3),
 (1,2,4);
select * from t;

update t 
set id2=null,
id1=id2

where id1=2;
select * from t

输出将为

id id1 id2
1  null null
1  null null

但是如果您这样做,那么输出结果将低于

update t 
set 
id1=id2,
id2=null

id id1 id2
1  3   null
1  4   null

顺序是set子句中的问题