COPY
filen till en temporär mellanställningstabell och uppdatera den faktiska tabellen därifrån. Gilla:
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
Om den importerade tabellen matchar den tabell som ska uppdateras exakt kan detta vara praktiskt:
CREATE TEMP TABLE tmp_x AS SELECT * FROM tbl LIMIT 0;
Skapar en tom temporär tabell som matchar strukturen i den befintliga tabellen, utan begränsningar.
Behörigheter
Upp till Postgres 10, SQL COPY
kräver superanvändarprivilegier för detta.
I Postgres 11 eller senare finns det även några fördefinierade roller (tidigare "standardroller") för att tillåta det. Manualen:
COPY
att namnge en fil eller ett kommando är endast tillåtet för databassuperanvändare eller användare som tilldelas en av rollernapg_read_server_files
,pg_write_server_files
, ellerpg_execute_server_program
[...]
psql metakommando \copy
fungerar för alla db-roller. Manualen:
Utför en frontend (klient) kopia. Detta är en operation som kör anSQL
COPY
kommandot, men istället för att servern läser eller skriver den angivna filen, läser eller skriver psql filen och dirigerar data mellan servern och det lokala filsystemet. Detta betyder att filtillgänglighet och privilegier är de för den lokala användaren, inte servern, och inga SQL-superanvändarbehörigheter krävs.
Omfattningen av temporära tabeller är begränsad till en enda session av en enda roll, så ovanstående måste köras i samma psql-session:
CREATE TEMP TABLE ...;
\copy tmp_x FROM '/absolute/path/to/file' (FORMAT csv);
UPDATE ...;
Om du skriptar det här i ett bash-kommando, se till att slå in allt i en enkel psql-anrop. Gilla:
echo 'CREATE TEMP TABLE tmp_x ...; \copy tmp_x FROM ...; UPDATE ...;' | psql
Normalt behöver du metakommandot \\
för att växla mellan psql-metakommandon och SQL-kommandon i psql, men \copy
är ett undantag från denna regel. Manualen igen:
särskilda tolkningsregler gäller för
\copy
meta-kommando. Till skillnad från de flesta andra metakommandon, anses hela resten av raden alltid vara argumenten för\copy
, och varken variabel interpolation eller backquote-expansion utförs i argumenten.
Stora bord
Om importtabellen är stor kan det löna sig att öka temp_buffers
tillfälligt för sessionen (det första i sessionen):
SET temp_buffers = '500MB'; -- example value
Lägg till ett index i den tillfälliga tabellen:
CREATE INDEX tmp_x_id_idx ON tmp_x(id);
Och kör ANALYZE
manuellt, eftersom temporära tabeller inte täcks av autovakuum / autoanalys.
ANALYZE tmp_x;
Relaterade svar:
- Bästa sättet att ta bort miljontals rader efter ID
- Hur kan jag infoga vanliga data i en tillfällig tabell från olika scheman?
- Hur tar man bort dubbletter av poster?