PostgreSQL kullanarak aynı sorgudaki birden çok satırı güncelleme


192

Bir ifadede PostgreSQL birden çok satır güncellemek için arıyorum. Aşağıdaki gibi bir şey yapmanın bir yolu var mı?

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

Onu o sayfada bulmaya çalışıyorum ama elde edemiyorum. Bir where deyimini kullanarak birden çok satırı güncelleyebileceğiniz yeri görüyorum, ancak her birinin kendi where deyimi ile birden çok satırı nasıl güncelleyeceğimi bilmiyorum. Ayrıca Google'da arama yaptım ve birisinin bu konuda net bir örnek vermesini umduğum için net bir cevap bulamadım.
newUserNameHere

Üzgünüm, benim hatam. Güncellenmiş.
zero323

Yanıtlar:


427

Ayrıca kullanabilirsiniz update ... from sözdizimi ve bir eşleme tablosu kullanabilirsiniz. Birden fazla sütunu güncellemek istiyorsanız, çok daha genelleştirilebilir:

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;

İstediğiniz kadar sütun ekleyebilirsiniz:

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 fiddle demo


11
Ayrıca, doğru bir veri türü belirtmek gerekebilir. ... from (values ('2014-07-21'::timestamp, 1), ('2014-07-20', 2), ...
Tarihli

Harika çalışıyor, açıkladığınız için teşekkürler! Bunun için Postgres belgeleri biraz kafa karıştırıcı bir okuma yapar.
skwidbreth

52

@Roman'ın çözümüne dayanarak, birden fazla değer ayarlayabilirsiniz:

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;

4
Bu onun çözümü gibi görünüyor .. NEREDEN (DEĞERLER ...) GÜNCELLEME. Sadece nasıl dayanıyor?
Evan Carroll

14
Bu yanıtı tercih ediyorum çünkü değişken isimleri neler olup bittiğini anlamayı kolaylaştırıyor.
Jon Lemmon

Vay. Hassas ve net. GoLang'da böyle bir şey uygulamaya çalışıyorum. Öyleyse değerler için bir dizi yapıyı aktarabilir miyim? Böyle bir şey, from (values $1)$ 1 bir yapı dizisidir. Yukarıdaki durumda, katı özellik olarak id, first_name ve last_name olur.
Reshma Suresh

26

Evet yapabilirsin:

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')

Ve çalışma kanıtı: http://sqlfiddle.com/#!2/97c7ea/1


8
Bu yanlıştır ... Bunu olmasa bile, tüm satırları güncelleyecek '123'ne de '345'. Kullanmalısınız WHERE column_b IN ('123','456')...
MatheusOl

1
sanırım '456'olması gerekiyor'345'
Roman Pekar

2
ELSE column_bSon WHEN ? THEN ?satırdan sonra eklerseniz , sütun geçerli değerine ayarlanır ve böylece MatheusQI'nin söylediklerini önler.
Kevin Orriss


OP'nin istediği tam olarak değil mi - birden fazla sütun değil, yalnızca column_a'nın güncellenmesi gerekiyor (column_b değerine göre), değil mi?
kevlarr

3

Benzer bir senaryoya rastladı ve CASE ifadesi benim için yararlı oldu.

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

Raporlar - buradaki bir tablodur; account_id, yukarıda belirtilen report_ids için aynıdır. Yukarıdaki sorgu 1 kaydı (koşulla eşleşen kayıt) true olarak ve eşleşmeyen tüm kayıtları false olarak ayarlar.


2

Tek bir sorguda birden çok satırı güncellemek için bunu deneyebilirsiniz

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

ek koşula ihtiyacınız yoksa andbu sorgunun bir kısmını kaldırın


0

Diyelim ki bir dizi kimliğiniz ve eşdeğer bir durum diziniz var - burada dizilerin statik bir SQL (farklı değerler nedeniyle değişmeyen bir sql sorgusu) ile nasıl yapılacağına bir örnek:

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;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.