Tôi đang tìm cách cập nhật nhiều hàng trong PostgreSQL trong một tuyên bố. Có cách nào để làm một cái gì đó như sau?
UPDATE table
SET
column_a = 1 where column_b = '123',
column_a = 2 where column_b = '345'
Tôi đang tìm cách cập nhật nhiều hàng trong PostgreSQL trong một tuyên bố. Có cách nào để làm một cái gì đó như sau?
UPDATE table
SET
column_a = 1 where column_b = '123',
column_a = 2 where column_b = '345'
Câu trả lời:
Bạn cũng có thể sử dụng update ... from
cú pháp và sử dụng bảng ánh xạ. Nếu bạn muốn cập nhật nhiều hơn một cột, thì nó khái quát hơn nhiều:
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;
Bạn có thể thêm bao nhiêu cột tùy thích:
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;
... from (values ('2014-07-21'::timestamp, 1), ('2014-07-20', 2), ...
Chi tiết khác tại Tài liệu PostgreSQL
Dựa trên giải pháp của @Roman, bạn có thể đặt nhiều giá trị:
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;
from (values $1)
đó $ 1 là một mảng các cấu trúc. Trong trường hợp trên, nghiêm ngặt sẽ có id, First_name và last_name làm thuộc tính.
Vâng, bạn có thể:
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')
Và bằng chứng làm việc: http://sqlfiddle.com/#!2/97c7ea/1
'123'
cũng không '345'
. Bạn nên sử dụng WHERE column_b IN ('123','456')
...
'456'
là phải thế'345'
ELSE column_b
vào sau WHEN ? THEN ?
dòng cuối cùng thì cột sẽ được đặt thành giá trị hiện tại, do đó ngăn chặn những gì MatheusQI nói sẽ xảy ra.
Chuyển qua kịch bản tương tự và biểu thức CASE rất hữu ích với tôi.
UPDATE reports SET is_default =
case
when report_id = 123 then true
when report_id != 123 then false
end
WHERE account_id = 321;
Báo cáo - là một bảng ở đây, account_id giống với báo cáo được đề cập ở trên. Truy vấn trên sẽ đặt 1 bản ghi (bản ghi khớp với điều kiện) thành true và tất cả các bản ghi không khớp thành false.
Để cập nhật nhiều hàng trong một truy vấn, bạn có thể thử điều này
UPDATE table_name
SET
column_1 = CASE WHEN any_column = value and any_column = value THEN column_1_value end,
column_2 = CASE WHEN any_column = value and any_column = value THEN column_2_value end,
column_3 = CASE WHEN any_column = value and any_column = value THEN column_3_value end,
.
.
.
column_n = CASE WHEN any_column = value and any_column = value THEN column_n_value end
nếu bạn không cần điều kiện bổ sung thì hãy xóa and
một phần của truy vấn này
Giả sử bạn có một mảng ID và mảng trạng thái tương đương - đây là một ví dụ về cách thực hiện điều này với SQL tĩnh (truy vấn sql không thay đổi do các giá trị khác nhau) của các mảng:
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;