sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur uppdaterar man valda rader med värden från en CSV-fil i Postgres?

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 rollerna pg_read_server_files ,pg_write_server_files , eller pg_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?


  1. Entity-framework-koden är långsam när du använder Include() många gånger

  2. Hur man distribuerar Chamilo MySQL-databasen för hög tillgänglighet

  3. SQLite aggregerade funktioner

  4. SQL BESTÄLLNING EFTER:De 5 bör och inte göra för att sortera data som ett proffs