COPY
filen til en midlertidig iscenesættelsestabel og opdater den faktiske tabel derfra. Ligesom:
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
Hvis den importerede tabel matcher den tabel, der skal opdateres nøjagtigt, kan dette være praktisk:
CREATE TEMP TABLE tmp_x AS SELECT * FROM tbl LIMIT 0;
Opretter en tom midlertidig tabel, der matcher strukturen af den eksisterende tabel, uden begrænsninger.
Privilegier
Op til Postgres 10, SQL COPY
kræver superbruger-rettigheder til dette.
I Postgres 11 eller nyere er der også nogle foruddefinerede roller (tidligere "standardroller") for at tillade det. Manualen:
COPY
navngivning af en fil eller kommando er kun tilladt for databasesuperbrugere eller brugere, der er tildelt en af rollerne pg_read_server_files
,pg_write_server_files
, eller pg_execute_server_program
[...]
psql meta-kommando \copy
virker til enhver db-rolle. Manualen:
Udfører en frontend (klient) kopi. Dette er en operation, der kører anSQL COPY
kommandoen, men i stedet for at serveren læser eller skriver den angivne fil, læser eller skriver psql filen og dirigerer data mellem serveren og det lokale filsystem. Dette betyder, at filtilgængelighed og privilegier er dem, der tilhører den lokale bruger, ikke serveren, og der kræves ingen SQL-superbrugerprivilegier.
Omfanget af midlertidige tabeller er begrænset til en enkelt session af en enkelt rolle, så ovenstående skal udføres i samme psql-session:
CREATE TEMP TABLE ...;
\copy tmp_x FROM '/absolute/path/to/file' (FORMAT csv);
UPDATE ...;
Hvis du scripter dette i en bash-kommando, skal du sørge for at pakke det hele i en enkelt psql opkald. Ligesom:
echo 'CREATE TEMP TABLE tmp_x ...; \copy tmp_x FROM ...; UPDATE ...;' | psql
Normalt har du brug for metakommandoen \\
at skifte mellem psql-metakommandoer og SQL-kommandoer i psql, men \copy
er en undtagelse fra denne regel. Manualen igen:
særlige parsingregler gælder for \copy
meta-kommando. I modsætning til de fleste andre metakommandoer bliver hele resten af linjen altid taget for at være argumenterne for \copy
, og hverken variabel interpolation eller backquote-udvidelse udføres i argumenterne.
Store borde
Hvis import-tabellen er stor, kan det betale sig at øge temp_buffers
midlertidigt til sessionen (det første i sessionen):
SET temp_buffers = '500MB'; -- example value
Tilføj et indeks til den midlertidige tabel:
CREATE INDEX tmp_x_id_idx ON tmp_x(id);
Og kør ANALYZE
manuelt, da midlertidige tabeller ikke er dækket af autovakuum / auto-analyse.
ANALYZE tmp_x;
Relaterede svar:
- Bedste måde at slette millioner af rækker efter ID
- Hvordan kan jeg indsætte almindelige data i en midlertidig tabel fra forskellige skemaer?
- Hvordan sletter man duplikerede poster?