sql >> Database teknologi >  >> RDS >> PostgreSQL

Hvordan opdaterer man valgte rækker med værdier fra en CSV-fil i Postgres?

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?


  1. Kører Vitess og MySQL med ClusterControl

  2. Hvordan sammenkædes kolonner i en Postgres SELECT?

  3. Tilslut tabeller med SUM-problem i MYSQL

  4. Tendenser i 2020, som DBA'er bør være opmærksomme på