COPY
o arquivo para uma tabela de preparo temporária e atualize a tabela real de lá. Como:CREATE TEMP TABLE tmp_x (id int, apple text, banana text); -- but see below
COPY tmp_x FROM '/absolute/path/to/file' (FORMAT csv);
UPDATE tbl
SET banana = tmp_x.banana
FROM tmp_x
WHERE tbl.id = tmp_x.id;
DROP TABLE tmp_x; -- else it is dropped at end of session automatically
Se a tabela importada corresponder exatamente à tabela a ser atualizada, isso pode ser conveniente:
CREATE TEMP TABLE tmp_x AS SELECT * FROM tbl LIMIT 0;
Cria uma tabela temporária vazia que corresponde à estrutura da tabela existente, sem restrições.
Privilégios
Até Postgres 10, SQL
COPY
requer privilégios de superusuário para isso.No Postgres 11 ou posterior, também existem algumas funções predefinidas (anteriormente "funções padrão") para permitir isso. O manual:
COPY
nomear um arquivo ou comando só é permitido a superusuários do banco de dados ou usuários que recebem uma das funçõespg_read_server_files
,pg_write_server_files
, oupg_execute_server_program
[...]
O psql meta-comando
\copy
funciona para qualquer função de banco de dados. O manual:
Executa uma cópia de frontend (cliente). Esta é uma operação que executa um SQLCOPY
mas em vez do servidor ler ou gravar o arquivo especificado, o psql lê ou grava o arquivo e roteia os dados entre o servidor e o sistema de arquivos local. Isso significa que a acessibilidade e os privilégios do arquivo são aqueles do usuário local, não do servidor, e nenhum privilégio de superusuário SQL é necessário.
O escopo das tabelas temporárias é limitado a uma única sessão de um único papel, então o acima deve ser executado na mesma sessão do psql:
CREATE TEMP TABLE ...;
\copy tmp_x FROM '/absolute/path/to/file' (FORMAT csv);
UPDATE ...;
Se você estiver criando um script em um comando bash, certifique-se de envolver tudo em um único chamada psql. Como:
echo 'CREATE TEMP TABLE tmp_x ...; \copy tmp_x FROM ...; UPDATE ...;' | psql
Normalmente, você precisa do meta-comando
\\
para alternar entre comandos meta do psql e comandos SQL no psql, mas \copy
é uma exceção a esta regra. O manual novamente:
regras especiais de análise se aplicam ao\copy
meta-comando. Ao contrário da maioria dos outros metacomandos, todo o restante da linha é sempre considerado como sendo os argumentos de\copy
, e nem a interpolação de variável nem a expansão de backquote são executadas nos argumentos.
Mesas grandes
Se a tabela de importação for grande, pode valer a pena aumentar
temp_buffers
temporariamente para a sessão (primeira coisa na sessão):SET temp_buffers = '500MB'; -- example value
Adicione um índice à tabela temporária:
CREATE INDEX tmp_x_id_idx ON tmp_x(id);
E execute
ANALYZE
manualmente, pois as tabelas temporárias não são cobertas pelo autovacuum / auto-analyze. ANALYZE tmp_x;
Respostas relacionadas:
- Melhor maneira de excluir milhões de linhas por ID
- Como posso inserir dados comuns em uma tabela temporária de esquemas diferentes?
- Como excluir entradas duplicadas?