更新表列,然后更新前一个更新值的另一列。 MySQL / PostgreSQL不同

时间:2016-11-12 12:44:43

标签: mysql sql postgresql multiple-columns

create table test (
    id serial primary key,
    c1 int,
    c2 int
);

insert into test (c1,c2) values (1,1);

 -- here (id, c1, c2) = (1, 1, 1)

update test set c1=2, c2=c1+2;

SELECT * FROM  test ;

MySQL给出(1,2,4),Postgres给出(1,2,3)。

我希望PostgreSQL的行为像MySQL一样,使用更新的值而不是原始值。可能吗?否则,如果我在列上有索引并且执行两次更新而不是一次,那么我有不必要的UPDATE = DELETE + INSERT(对于PostgreSQL),并将工作加倍。在特殊情况下,我实际上必须进行4次更新而不是一次:(。在SQL之外做一些添加很容易,但我有SQL相关的功能。

N.B。据我所知,UPDATE = DELETE + INSERT可能不是数字类型的情况,或者它是否有索引?对于varchars,它总是如此。

1 个答案:

答案 0 :(得分:2)

Postgres是对的。根据MySQL文档:

  

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

UPDATE t1 SET col1 = col1 + 1, col2 = col1;

我认为你不应该要求Postgres被打破。

Postgres(和ANSI)使用的逻辑很简单。在更新语句中,SET左侧的值引用 new 记录;右边的值是指记录。作业的顺序并不重要。

MySQL有不同的规则。

在Postgres中,你可以做这样的事情:

update test
    set c1 = t1.new_c1, c2 = new_c1 + 2
    from (select t1.*, 2 as new_c1
          from test t1
         ) t1
    where test.id = t1.id;

显然,对于一个简单的常量来说这是矫枉过正,但对于一个复杂的表达式,它可能有意义。此外,由于JOIN位于主键上,因此对性能的影响很小。