Je cherche à mettre à jour plusieurs lignes dans PostgreSQL dans une seule déclaration. Existe-t-il un moyen de faire quelque chose comme ce qui suit?
UPDATE table
SET
column_a = 1 where column_b = '123',
column_a = 2 where column_b = '345'
Je cherche à mettre à jour plusieurs lignes dans PostgreSQL dans une seule déclaration. Existe-t-il un moyen de faire quelque chose comme ce qui suit?
UPDATE table
SET
column_a = 1 where column_b = '123',
column_a = 2 where column_b = '345'
Réponses:
Vous pouvez également utiliser la update ... from
syntaxe et utiliser une table de mappage. Si vous souhaitez mettre à jour plus d'une colonne, c'est beaucoup plus généralisable:
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;
Vous pouvez ajouter autant de colonnes que vous le souhaitez:
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), ...
Plus de détails dans la documentation PostgreSQL
Sur la base de la solution de @Roman, vous pouvez définir plusieurs valeurs:
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)
Où $ 1 est un tableau de structures. Dans le cas ci-dessus, le strict aurait comme propriétés id, first_name et last_name.
Oui, vous pouvez:
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')
Et preuve de travail: http://sqlfiddle.com/#!2/97c7ea/1
'123'
ni '345'
. Vous devriez utiliser WHERE column_b IN ('123','456')
...
'456'
censé être'345'
ELSE column_b
après la dernière WHEN ? THEN ?
ligne, la colonne sera définie sur sa valeur actuelle, empêchant ainsi ce que MatheusQI a dit de se produire.
Je suis tombé sur un scénario similaire et l'expression CASE m'a été utile.
UPDATE reports SET is_default =
case
when report_id = 123 then true
when report_id != 123 then false
end
WHERE account_id = 321;
Rapports - est un tableau ici, account_id est le même pour les report_ids mentionnés ci-dessus. La requête ci-dessus définira 1 enregistrement (celui qui correspond à la condition) sur true et tous les enregistrements non correspondants sur false.
Pour mettre à jour plusieurs lignes dans une seule requête, vous pouvez essayer ceci
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
si vous n'avez pas besoin de condition supplémentaire, supprimez une and
partie de cette requête
Supposons que vous ayez un tableau d' ID et un tableau équivalent de statuts - voici un exemple comment faire cela avec un SQL statique (une requête SQL qui ne change pas en raison de valeurs différentes) des tableaux:
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;