使用PostgreSQL在同一个查询中更新多行

我正在寻找在一个语句中更新PostgreSQL中的多个行。 有没有办法做下面的事情?

UPDATE table SET column_a = 1 where column_b = '123', column_a = 2 where column_b = '345' 

您也可以使用update ... from语法和使用映射表。 如果你想更新多个列,这是更普遍的:

 update test as t set column_a = c.column_a from (values ('123', 1), ('345', 2) ) as c(column_b, column_a) where c.column_b = t.column_b; 

您可以添加尽可能多的列,只要你喜欢:

 update test as t set column_a = c.column_a, column_c = c.column_c from (values ('123', 1, '---'), ('345', 2, '+++') ) as c(column_b, column_a, column_c) where c.column_b = t.column_b; 

sql小提琴演示

是的你可以:

 UPDATE foobar SET column_a = CASE WHEN column_b = '123' THEN 1 WHEN column_b = '345' THEN 2 END WHERE column_b IN ('123','345') 

和工作certificate: http : //sqlfiddle.com/#!2/97c7ea/1

基于@Roman的解决scheme,您可以设置多个值:

 update users as u set -- postgres FTW email = u2.email, first_name = u2.first_name, last_name = u2.last_name from (values (1, 'hollis@weimann.biz', 'Hollis', 'O\'Connell'), (2, 'robert@duncan.info', 'Robert', 'Duncan') ) as u2(id, email, first_name, last_name) where u2.id = u.id; 

遇到类似的情况,CASEexpression对我有用。

 UPDATE reports SET is_default = case when report_id = 123 then true when report_id != 123 then false end WHERE account_id = 321; 

报告 – 在这里是一个表格,account_id与上面提到的report_ids相同。 上面的查询将把1个logging(与条件匹配的logging)设置为true,将所有不匹配的logging设置为false。

比方说,你有一个ID数组和等价的状态数组 – 这里是一个例子,如何使用静态SQL(一个SQL查询不会因为不同的值而改变)数组:

 drop table if exists results_dummy; create table results_dummy (id int, status text, created_at timestamp default now(), updated_at timestamp default now()); -- populate table with dummy rows insert into results_dummy (id, status) select unnest(array[1,2,3,4,5]::int[]) as id, unnest(array['a','b','c','d','e']::text[]) as status; select * from results_dummy; -- THE update of multiple rows with/by different values update results_dummy as rd set status=new.status, updated_at=now() from (select unnest(array[1,2,5]::int[]) as id,unnest(array['a`','b`','e`']::text[]) as status) as new where rd.id=new.id; select * from results_dummy; -- in code using **IDs** as first bind variable and **statuses** as the second bind variable: update results_dummy as rd set status=new.status, updated_at=now() from (select unnest(:1::int[]) as id,unnest(:2::text[]) as status) as new where rd.id=new.id;