web-dev-qa-db-fra.com

La commande Postgres client copy (\ copy) n'a pas accès à une table temporaire?

Je génère une liste de commandes SQL pour exporter certaines données que j'exécute finalement en utilisant psql -f. Les requêtes obtiennent toutes le même sous-ensemble de données, donc j'ai pensé que je prendrais en compte les qualifications et mettrais une liste des identifiants utilisateur éligibles dans des tables temporaires comme ceci

create temporary table tmp_export_users as (select id from users where ...)

puis référez-vous à cela dans mes commandes\copy comme

\copy (select ... from table where user_id in (select id from tmp_export_users)) TO 'filename.csv' WITH CSV HEADER

Ce sont tous dans le même fichier, un par ligne, et en les exécutant -f je reçois l'erreur que les commandes de copie ne peuvent pas voir la table temporaire, donc je suppose que la commande de copie client ne doit pas réellement utiliser les mêmes postgres session en psql.

Est-ce exact? Y a-t-il un moyen de changer ce comportement?

8
jkebinger

\copy peut utiliser une table temporaire.

J'ai d'abord testé et confirmé cela avec la version 9.0 sur la ligne de commande.
Ensuite, j'ai créé un fichier avec la commande SQL et psql meta \copy en utilisant plusieurs tables temporaires. Cela a également fonctionné pour moi.

CREATE TEMP TABLE tmp as SELECT * FROM tbl;
\copy (SELECT * FROM tmp JOIN tbl USING (id)) TO '/var/lib/postgres/test1.csv';

Appel:

psql -p5432 mydb -f test.sql

Notez le point-virgule de fin, qui est facultatif à la fin d'un fichier (terminé implicitement), mais obligatoire après toute autre instruction SQL et également après la dernière si elle est exécutée en psql de manière interactive.

Normalement , les méta-commandes psql ne peuvent pas être mélangées avec SQL sur la même ligne dans un fichier exécuté par psql -f. Je cite le manuel sur psql :

L'analyse des arguments s'arrête à la fin de la ligne ou lorsqu'une autre barre oblique inversée est trouvée. Une barre oblique inverse sans guillemets est considérée comme le début d'une nouvelle méta-commande. La séquence spéciale \\ (deux barres obliques inverses) marque la fin des arguments et continue l'analyse des commandes SQL, le cas échéant. De cette façon, les commandes SQL et psql peuvent être librement mélangées sur une ligne. Mais dans tous les cas, les arguments d'une méta-commande ne peuvent pas continuer au-delà de la fin de la ligne.

Différentes règles s'appliquent après\copy, bien que. Essentiellement, psql repasse automatiquement en mode SQL après \copy Voir:

Mais vous avez écrit que vous aviez toutes les commandes sur des lignes distinctes. Cela ne peut donc pas être l'explication dans votre cas.


Tout cela mis à part, avez-vous envisagé d'utiliser COPY (la commande SQL ) au lieu de \copy (la méta-commande psql )?

Bien sûr, le fichier cible devrait être local sur le serveur et non sur le client dans ce cas. Et différents privilèges de fichiers s'appliquent. Le manuel :

Les fichiers nommés dans une commande COPY sont lus ou écrits directement par le serveur, pas par l'application cliente. Par conséquent, ils doivent résider ou être accessibles à la machine du serveur de base de données, pas au client. Ils doivent être accessibles et lisibles ou accessibles en écriture par l'utilisateur PostgreSQL (l'ID utilisateur sous lequel le serveur s'exécute), et non par le client.

16