Обновление нескольких строк с другим первичным ключом в одном запросе в PostgreSQL?
Мне нужно обновить многие столбцы во многих строках в PostgreSQL 9.1. В настоящее время я делаю это со многими различными запросами UPDATE
, каждый из которых работает в другой строке (на основе первичного ключа):
UPDATE mytable SET column_a = 12, column_b = 6 WHERE id = 1;
UPDATE mytable SET column_a = 1, column_b = 45 WHERE id = 2;
UPDATE mytable SET column_a = 56, column_b = 3 WHERE id = 3;
Мне нужно выполнить несколько тысяч этих запросов.
В любом случае я могу "массовое обновление" множества строк в одном запросе в PostgreSQL? Если вы используете INSERT
, вы можете вставить сразу несколько строк: (INSERT INTO mytable (column_a, column_b) VALUES ( (12, 6), (1, 45) );
), есть ли что-то подобное для UPDATE
?
Что-то вроде:
UPDATE mytable SET (id, column_a, column_b) FROM VALUES ( (1, 12, 6), (2, 1, 45), (3, 56, 3), … )
??
Важным моментом является то, что каждое "VALUE" будет обновлять только одну строку (на основе WHERE id =
). Каждая строка будет иметь одинаковое фиксированное количество столбцов, которые нуждаются в обновлении, но каждая строка будет иметь разные значения для каждого столбца, поэтому UPDATE mytable SET column_a = 12, column_b = 6 WHERE id IN (1, 2, 3);
не будет работать.
Ответы
Ответ 1
Да, вы можете (и обычно предпочитаете в SQL) обновлять сразу несколько строк. Есть несколько способов сделать это, но большинство читаемых и элегантных, я думаю, это использовать производную таблицу с id и значениями:
update mytable as m set
column_a = c.column_a,
column_b = c.column_b
from (values
(1, 12, 6),
(2, 1, 45),
(3, 56, 3)
) as c(id, column_a, column_b)
where c.id = m.id
Не так читаемо, но более очевидным решением было бы использовать case
:
update mytable set
column_a = case id when 1 then 12 when 2 then 1 when 3 then 56 end,
column_b = case id when 1 then 6 when 2 then 45 when 3 then 3 end
where id in (1, 2, 3)
Ответ 2
Если это применимо к вашему делу, вы можете его использовать.
create table test(id int, a int, b int);
insert into test(id, a, b)
values
(1, 1, 1),
(2, 1, 1),
(3, 1, 1),
(4, 1, 1),
(5, 1, 1),
(6, 1, 1),
(7, 1, 1);
update test as d
set a = s.a, b = s.b
from
(
values
(1, 2, 2),
(2, 2, 2)
) as s(id, a, b)
where d.id = s.id
SQL FIDDLE DEMO