PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Atualização em massa/lote/upsert no PostgreSQL

Inserção em massa


Você pode modificar a inserção em massa de três colunas por @Ketema:
INSERT INTO "table" (col1, col2, col3)
  VALUES (11, 12, 13) , (21, 22, 23) , (31, 32, 33);

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

Substituindo os valores por espaços reservados:
INSERT INTO "table" (col1, col2, col3)
  VALUES (unnest(?), unnest(?), unnest(?))

Você tem que passar arrays ou listas como argumentos para esta consulta. Isso significa que você pode fazer grandes inserções em massa sem fazer concatenação de strings (e todos os seus problemas e perigos:injeção de sql e citações infernais).

Atualização em massa


O PostgreSQL adicionou a extensão FROM ao UPDATE. Você pode usá-lo desta forma:
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;

O manual está faltando uma boa explicação, mas há um exemplo na lista de discussão postgresql-admin. Tentei detalhar:
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;
 

Há também outras postagens no StackExchange explicando UPDATE...FROM.. usando um VALUES cláusula em vez de uma subconsulta. Eles podem ser mais fáceis de ler, mas estão restritos a um número fixo de linhas.