J'utilise Postgres et j'aimerais faire une grande requête de mise à jour qui serait extraite d'un fichier CSV, disons que j'ai un tableau qui a (id, banana, Apple)
.
Je voudrais exécuter une mise à jour qui change les bananes et non les pommes, chaque nouvelle banane et leur identifiant seraient dans un fichier CSV.
J'ai essayé de regarder le site Postgres mais les exemples me tuent.
COPY
le fichier dans une table de transfert temporaire et mettez à jour la table à partir de cet emplacement. Comme:
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
Si la table importée correspond exactement à la table à mettre à jour, cela peut être pratique:
CREATE TEMP TABLE tmp_x AS SELECT * FROM tbl LIMIT 0;
Crée une table temporaire vide correspondant à la structure de la table existante, sans contrainte.
SQL COPY
nécessite des privilèges de superutilisateur pour cela. ( Le manuel ):
COPY
l'attribution de nom à un fichier ou à une commande est uniquement autorisée pour les super-utilisateurs de la base de données, car elle permet de lire ou d'écrire tout fichier auquel le serveur dispose de privilèges d'accès.
La psql méta-commande \copy
fonctionne pour tout rôle de base de données. Le manuel:
Effectue une copie frontale (client). Il s’agit d’une opération qui exécute une commande SQL
COPY
, mais au lieu que le serveur lise ou écrit le fichier spécifié, psql lit ou écrit le fichier et achemine les données entre le serveur et le serveur. système de fichiers local. Cela signifie que l'accessibilité aux fichiers et les privilèges sont ceux de l'utilisateur local, et non du serveur, et qu'aucun privilège superutilisateur SQL n'est requis.
La portée des tables temporaires est limitée à un seul session d'un seul rôle. Le précédent doit donc être exécuté dans la même session psql:
CREATE TEMP TABLE ...;
\copy tmp_x FROM '/absolute/path/to/file' (FORMAT csv);
UPDATE ...;
Si vous écrivez ceci dans une commande bash, veillez à envelopper le tout dans un appel single psql. Comme:
echo 'CREATE TEMP TABLE tmp_x ...; \copy tmp_x FROM ...; UPDATE ...;' | psql
Normalement, vous avez besoin de la méta-commande \\
pour basculer entre les commandes méta psql et les commandes SQL dans psql, mais \copy
est une exception à cette règle. Le manuel à nouveau:
des règles d'analyse spéciales s'appliquent à la
\copy
méta-commande. Contrairement à la plupart des autres méta-commandes, le reste de la ligne est toujours considéré comme les arguments de\copy
, et ni l’interpolation de variable ni l’agrandissement de cotes arrière ne sont effectués dans les arguments.
Si la table d'importation est grande, il peut être intéressant d'augmenter temp_buffers
temporairement pour la session (première chose dans la session):
SET temp_buffers = '500MB'; -- example value
Ajoutez un index à la table temporaire:
CREATE INDEX tmp_x_id_idx ON tmp_x(id);
Et exécutez ANALYZE
manuellement, car les tables temporaires ne sont pas couvertes par autovacuum/auto-analysis.
ANALYZE tmp_x;
Réponses associées: