sql >> Base de Datos >  >> RDS >> PostgreSQL

Actualización masiva/por lotes/upsert en PostgreSQL

Inserto a granel

Puede modificar la inserción masiva de tres columnas por @Ketema:

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

Se convierte en:

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

Reemplazando los valores con marcadores de posición:

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

Debe pasar matrices o listas como argumentos a esta consulta. Esto significa que puede hacer inserciones masivas enormes sin hacer una concatenación de cadenas (y todos sus problemas y peligros:inyección de sql y citas infernales).

Actualización masiva

PostgreSQL ha agregado la extensión FROM a UPDATE. Puedes usarlo de esta manera:

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;

Al manual le falta una buena explicación, pero hay un ejemplo en la lista de correo de postgresql-admin. Traté de explicarlo:

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;
 

También hay otras publicaciones en StackExchange que explican UPDATE...FROM.. usando un VALUES cláusula en lugar de una subconsulta. Pueden ser más fáciles de leer, pero están restringidos a un número fijo de filas.