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,它总是如此。
答案 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
位于主键上,因此对性能的影响很小。