COPY
le fichier dans une table intermédiaire temporaire et mettre à jour la table réelle à partir de là. 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 contraintes.
Privilèges
Jusqu'à Postgres 10, SQL COPY
nécessite des privilèges de superutilisateur pour cela.
Dans Postgres 11 ou version ultérieure, il existe également des rôles prédéfinis (anciennement "rôles par défaut") pour l'autoriser. Le manuel :
COPY
nommer un fichier ou une commande n'est autorisé qu'aux super-utilisateurs de la base de données ou aux utilisateurs qui ont l'un des rôlespg_read_server_files
,pg_write_server_files
, oupg_execute_server_program
[...]
Le psql méta-commande \copy
fonctionne pour n'importe quel rôle db. Le manuel :
Effectue une copie frontale (client). Il s'agit d'une opération qui exécute un SQL
COPY
, mais au lieu que le serveur lise ou écrive le fichier spécifié, psql lit ou écrit le fichier et achemine les données entre le serveur et le système de fichiers local. Cela signifie que l'accès aux fichiers et les privilèges sont ceux de l'utilisateur local, et non du serveur, et aucun privilège de superutilisateur SQL n'est requis.
La portée des tables temporaires est limitée à une seule session d'un seul rôle, donc ce qui précède doit ê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 cela dans une commande bash, assurez-vous de tout envelopper dans un single appel 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 méta-commandes psql et les commandes SQL dans psql, mais \copy
fait exception à cette règle. Encore le manuel :
des règles d'analyse spéciales s'appliquent au
\copy
méta-commande. Contrairement à la plupart des autres méta-commandes, le reste entier de la ligne est toujours considéré comme les arguments de\copy
, et ni l'interpolation de variable ni l'expansion des guillemets inversés ne sont effectuées dans les arguments.
Grandes tables
Si la table d'importation est grande, il peut être payant 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 lancez ANALYZE
manuellement, car les tables temporaires ne sont pas couvertes par autovacuum / auto-analyze.
ANALYZE tmp_x;
Réponses associées :
- Meilleur moyen de supprimer des millions de lignes par ID
- Comment puis-je insérer des données communes dans une table temporaire à partir de schémas disparates ?
- Comment supprimer les entrées en double ?