PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie aktualisiere ich ausgewählte Zeilen mit Werten aus einer CSV-Datei in Postgres?

COPY die Datei in eine temporäre Staging-Tabelle und aktualisieren Sie von dort aus die eigentliche Tabelle. Wie:

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

Wenn die importierte Tabelle genau mit der zu aktualisierenden Tabelle übereinstimmt, kann dies praktisch sein:

CREATE TEMP TABLE tmp_x AS SELECT * FROM tbl LIMIT 0;

Erstellt eine leere temporäre Tabelle, die ohne Einschränkungen der Struktur der vorhandenen Tabelle entspricht.

Privilegien

Bis Postgres 10, SQL COPY erfordert Superuser-Rechte dafür.
In Postgres 11 oder höher gibt es auch einige vordefinierte Rollen (ehemals "Standardrollen"), um dies zuzulassen. Das Handbuch:

COPY Das Benennen einer Datei oder eines Befehls ist nur Datenbank-Superusers oder Benutzern gestattet, denen eine der Rollen pg_read_server_files gewährt wurde ,pg_write_server_files , oder pg_execute_server_program [...]

Die psql Meta-Befehl \copy funktioniert für jede DB-Rolle. Das Handbuch:

Führt eine Frontend-(Client-)Kopie durch. Dies ist eine Operation, die ein SQL COPY ausführt Befehl, aber anstatt dass der Server die angegebene Datei liest oder schreibt, liest oder schreibt psql die Datei und leitet die Daten zwischen dem Server und dem lokalen Dateisystem weiter. Das bedeutet, dass Dateizugriff und -privilegien die des lokalen Benutzers sind, nicht die des Servers, und dass keine SQL-Superuser-Privilegien erforderlich sind.

Der Geltungsbereich temporärer Tabellen ist auf eine einzelne Sitzung beschränkt einer einzelnen Rolle, daher muss das obige in derselben psql-Sitzung ausgeführt werden:

CREATE TEMP TABLE ...;
\copy tmp_x FROM '/absolute/path/to/file' (FORMAT csv);
UPDATE ...;

Wenn Sie dies in einem Bash-Befehl schreiben, achten Sie darauf, alles in einen einzelnen zu packen psql-Aufruf. Wie:

echo 'CREATE TEMP TABLE tmp_x ...; \copy tmp_x FROM ...; UPDATE ...;' | psql

Normalerweise benötigen Sie den Meta-Befehl \\ um zwischen psql-Metabefehlen und SQL-Befehlen in psql zu wechseln, aber \copy ist eine Ausnahme von dieser Regel. Nochmal das Handbuch:

für \copy gelten spezielle Parsing-Regeln Meta-Befehl. Im Gegensatz zu den meisten anderen Meta-Befehlen wird der gesamte Rest der Zeile immer als Argument von \copy genommen , und in den Argumenten werden weder Variableninterpolation noch Backquote-Erweiterung durchgeführt.

Große Tische

Wenn die Import-Tabelle groß ist, kann es sich lohnen, temp_buffers zu erhöhen temporär für die Sitzung (als erstes in der Sitzung):

SET temp_buffers = '500MB';  -- example value

Fügen Sie der temporären Tabelle einen Index hinzu:

CREATE INDEX tmp_x_id_idx ON tmp_x(id);

Und führen Sie ANALYZE aus manuell, da temporäre Tabellen nicht von Autovacuum / Auto-Analyze erfasst werden.

ANALYZE tmp_x;

Verwandte Antworten:

  • Der beste Weg, um Millionen von Zeilen nach ID zu löschen
  • Wie kann ich gemeinsame Daten aus unterschiedlichen Schemas in eine temporäre Tabelle einfügen?
  • Wie lösche ich doppelte Einträge?