2016-11-12 1 views
3
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).Обновить столбец таблицы, затем другой столбец с обновленным значением первого. MySQL/PostgreSQL отличаются

Я бы хотел, чтобы PostgreSQL вел себя как MySQL, чтобы работать с обновленным значением, а не оригинальным. Является ли это возможным? В противном случае, если у меня есть индексы в столбце и два обновления вместо одного, то у меня есть ненужное UPDATE = DELETE + INSERT (для PostgreSQL) и удвоение работы. В частном случае на самом деле мне нужно сделать 4 обновления вместо одного :(. Делать добавление легко вне SQL, но вместо этого у меня есть функция, связанная с SQL.

NB Насколько я помню, UPDATE = DELETE + INSERT не может быть для числовых типов, или, если они имеют индексы для VARCHARS всегда верно

+0

Поскольку вы назначаете значение c1, почему бы не сделать 'c1 = 2, c2 = 2 + 2'? –

+0

Потому что, как я писал, это просто пример, на самом деле я использую функцию SQL вместо этого вместо этого. Я мог бы сделать это: c1 = f (c1), c2 = f2 (f (c1)), писать избыточно, но интересно, есть ли лучшее решение. – anonymous

+0

Хороший вопрос. Невозможно найти стандартное поведение SQL для UPDATE (поиск по SQL-источнику стандартного SQL) – Abelisto

ответ

2

Postgres прав Согласно документации MySQL:..

Второе назначение в следующих наборах отчетности col2 до текущее (обновленное) значение col1, а не исходное значение col1. Результат - это то, что col1 an d col2 имеют одинаковое значение. Это поведение отличается от стандартного SQL .

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

Я не думаю, что вы должны попросить Postgres быть сломанным.

Логика использования Postgres (и ANSI) проста. В заявлении об обновлении значения слева от SET относятся к записи ; значения справа относятся к старой записи. Порядок присвоений не имеет значения.

У 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 находится на первичных ключах, влияние на производительность незначительно.

+0

Я видел эти типы SQL, прежде чем обнаружил эту разницу в MySQL/PostgreSQL, и подозревал, что может быть причина для их использования :) – anonymous