PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Mise à jour/upsert en masse/par lots dans PostgreSQL

Insertion groupée

Vous pouvez modifier l'insertion en masse de trois colonnes par @Ketema :

INSERT INTO "table" (col1, col2, col3)
  VALUES (11, 12, 13) , (21, 22, 23) , (31, 32, 33);

Il devient :

INSERT INTO "table" (col1, col2, col3)
  VALUES (unnest(array[11,21,31]), 
          unnest(array[12,22,32]), 
          unnest(array[13,23,33]))

Remplacement des valeurs par des espaces réservés :

INSERT INTO "table" (col1, col2, col3)
  VALUES (unnest(?), unnest(?), unnest(?))

Vous devez passer des tableaux ou des listes comme arguments à cette requête. Cela signifie que vous pouvez faire d'énormes insertions en masse sans faire de concaténation de chaînes (et tous ses inconvénients et dangers :injection sql et guillemets infernaux).

Mise à jour groupée

PostgreSQL a ajouté l'extension FROM à UPDATE. Vous pouvez l'utiliser de cette manière :

update "table" 
  set value = data_table.new_value
  from 
    (select unnest(?) as key, unnest(?) as new_value) as data_table
  where "table".key = data_table.key;

Il manque une bonne explication au manuel, mais il y a un exemple sur la liste de diffusion postgresql-admin. J'ai essayé d'élaborer dessus :

create table tmp
(
  id serial not null primary key,
  name text,
  age integer
);

insert into tmp (name,age) 
values ('keith', 43),('leslie', 40),('bexley', 19),('casey', 6);

update tmp set age = data_table.age
from
(select unnest(array['keith', 'leslie', 'bexley', 'casey']) as name, 
        unnest(array[44, 50, 10, 12]) as age) as data_table
where tmp.name = data_table.name;
 

Il existe également d'autres articles sur StackExchange expliquant UPDATE...FROM.. en utilisant un VALUES clause au lieu d'une sous-requête. Ils peuvent être plus faciles à lire, mais sont limités à un nombre fixe de lignes.