COPY
il file in una tabella di staging temporanea e da lì aggiornare la tabella effettiva. Come:
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 la tabella importata corrisponde esattamente alla tabella da aggiornare, può essere conveniente:
CREATE TEMP TABLE tmp_x AS SELECT * FROM tbl LIMIT 0;
Crea una tabella temporanea vuota che corrisponde alla struttura della tabella esistente, senza vincoli.
Privilegi
Fino a Postgres 10, SQL COPY
richiede privilegi di superutente per questo.
In Postgres 11 o versioni successive, ci sono anche alcuni ruoli predefiniti (precedentemente "ruoli predefiniti") per consentirlo. Il manuale:
COPY
la denominazione di un file o di un comando è consentita solo ai superuser del database o agli utenti a cui è concesso uno dei ruoli pg_read_server_files
,pg_write_server_files
o pg_execute_server_program
[...]
Il psql meta-comando \copy
funziona per qualsiasi ruolo db. Il manuale:
Esegue una copia front-end (client). Questa è un'operazione che esegue un SQL COPY
comando, ma invece di leggere o scrivere il file specificato dal server, psql legge o scrive il file e instrada i dati tra il server e il file system locale. Ciò significa che l'accessibilità ai file e i privilegi sono quelli dell'utente locale, non del server, e non sono richiesti privilegi di superutente SQL.
L'ambito delle tabelle temporanee è limitato a una singola sessione di un singolo ruolo, quindi quanto sopra deve essere eseguito nella stessa sessione psql:
CREATE TEMP TABLE ...;
\copy tmp_x FROM '/absolute/path/to/file' (FORMAT csv);
UPDATE ...;
Se stai scrivendo questo in un comando bash, assicurati di racchiuderlo tutto in un singolo chiamata psql. Come:
echo 'CREATE TEMP TABLE tmp_x ...; \copy tmp_x FROM ...; UPDATE ...;' | psql
Normalmente, hai bisogno del meta-comando \\
per passare dai meta comandi psql ai comandi SQL in psql, ma \copy
è un'eccezione a questa regola. Il manuale di nuovo:
regole speciali di analisi si applicano a \copy
metacomando. A differenza della maggior parte degli altri meta-comandi, l'intero resto della riga viene sempre considerato come argomenti di \copy
, e negli argomenti non vengono eseguite né l'interpolazione delle variabili né l'espansione delle virgolette.
Tavoli grandi
Se la tabella di importazione è grande, potrebbe essere utile aumentare temp_buffers
temporaneamente per la sessione (prima cosa nella sessione):
SET temp_buffers = '500MB'; -- example value
Aggiungi un indice alla tabella temporanea:
CREATE INDEX tmp_x_id_idx ON tmp_x(id);
Ed esegui ANALYZE
manualmente, poiché le tabelle temporanee non sono coperte da autovacuum/auto-analyze.
ANALYZE tmp_x;
Risposte correlate:
- Il modo migliore per eliminare milioni di righe per ID
- Come posso inserire dati comuni in una tabella temporanea da schemi disparati?
- Come eliminare le voci duplicate?