Ich möchte mehrere Zeilen in PostgreSQL in einer Anweisung aktualisieren. Gibt es eine Möglichkeit, Folgendes zu tun?
UPDATE table
SET
column_a = 1 where column_b = '123',
column_a = 2 where column_b = '345'
Ich möchte mehrere Zeilen in PostgreSQL in einer Anweisung aktualisieren. Gibt es eine Möglichkeit, Folgendes zu tun?
UPDATE table
SET
column_a = 1 where column_b = '123',
column_a = 2 where column_b = '345'
Antworten:
Sie können auch die update ... from
Syntax und eine Zuordnungstabelle verwenden. Wenn Sie mehr als eine Spalte aktualisieren möchten, ist dies viel verallgemeinerbarer:
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;
Sie können beliebig viele Spalten hinzufügen:
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), ...
Weitere Details in der PostgreSQL-Dokumentation
Basierend auf der Lösung von @Roman können Sie mehrere Werte festlegen:
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 ist ein Array von Strukturen. Im obigen Fall hätte der Strict ID, Vorname und Nachname als Eigenschaften.
Ja, du kannst:
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')
Und Arbeitsnachweis: http://sqlfiddle.com/#!2/97c7ea/1
'123'
Fall ist '345'
. Sie sollten verwenden WHERE column_b IN ('123','456')
...
'456'
sollte sein'345'
ELSE column_b
nach der letzten WHEN ? THEN ?
Zeile hinzufügen , wird die Spalte auf den aktuellen Wert gesetzt, wodurch verhindert wird, dass das, was MatheusQI gesagt hat, passiert.
Kam über ein ähnliches Szenario und der CASE-Ausdruck war für mich nützlich.
UPDATE reports SET is_default =
case
when report_id = 123 then true
when report_id != 123 then false
end
WHERE account_id = 321;
Berichte - ist hier eine Tabelle, account_id ist für die oben genannten report_ids identisch. Bei der obigen Abfrage wird 1 Datensatz (derjenige, der der Bedingung entspricht) auf true und alle nicht übereinstimmenden auf false gesetzt.
Sie können dies versuchen, um mehrere Zeilen in einer einzigen Abfrage zu aktualisieren
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
Wenn Sie keine zusätzliche Bedingung benötigen, entfernen Sie einen and
Teil dieser Abfrage
Angenommen, Sie haben ein Array mit IDs und ein gleichwertiges Array mit Status. Hier ist ein Beispiel, wie dies mit einem statischen SQL (einer SQL-Abfrage, die sich aufgrund unterschiedlicher Werte nicht ändert) der Arrays durchgeführt wird:
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;