web-dev-qa-db-fra.com

Enregistrer la sortie PL / pgSQL de PostgreSQL dans un fichier CSV

Quel est le moyen le plus simple de sauvegarder la sortie PL/pgSQL d’une base de données PostgreSQL dans un fichier CSV?

J'utilise PostgreSQL 8.4 avec pgAdmin III et le plugin PSQL à partir duquel je lance les requêtes.

822
Hoff

Voulez-vous le fichier résultant sur le serveur ou sur le client?

Du côté serveur

Si vous voulez quelque chose de facile à réutiliser ou à automatiser, vous pouvez utiliser la commande COPY intégrée de Postgresql. par exemple.

_Copy (Select * From foo) To '/tmp/test.csv' With CSV DELIMITER ',';
_

Cette approche est entièrement exécutée sur le serveur distant - elle ne peut pas écrire sur votre PC local. Il doit également être exécuté en tant que "superutilisateur" Postgres (normalement appelé "racine") car Postgres ne peut pas l'empêcher de faire des bêtises avec le système de fichiers local de cette machine.

Cela ne signifie pas pour autant que vous devez être connecté en tant que superutilisateur (l'automatisation constituerait un risque de sécurité différent), car vous pouvez utiliser l'option _SECURITY DEFINER_ pour _CREATE FUNCTION_ pour créer une fonction qui s'exécute comme si vous étiez un superutilisateur .

La partie cruciale est que votre fonction est là pour effectuer des vérifications supplémentaires, pas seulement pour contourner la sécurité - vous pouvez donc écrire une fonction qui exporte les données exactes dont vous avez besoin, ou vous pouvez écrire quelque chose qui peut accepter diverses options tant qu'elles répondre à une liste blanche stricte. Vous devez vérifier deux choses:

  1. Quels fichiers l'utilisateur devrait-il être autorisé à lire/écrire sur le disque? Cela peut être un répertoire particulier, par exemple, et le nom du fichier doit avoir un préfixe ou une extension approprié.
  2. Quelles tables l'utilisateur devrait-il pouvoir lire/écrire dans la base de données? Cela devrait normalement être défini par GRANTs dans la base de données, mais la fonction s'exécute maintenant en tant que superutilisateur. Ainsi, les tables qui seraient normalement "hors limites" seront entièrement accessibles. Vous ne voulez probablement pas laisser quelqu'un invoquer votre fonction et ajouter des lignes à la fin de votre tableau "utilisateurs"…

J'ai écrit , un article de blog développant cette approche , avec quelques exemples de fonctions permettant d'exporter (ou d'importer) des fichiers et des tables répondant à des conditions strictes.


Côté client

L’autre approche consiste à gérer le fichier côté client , c’est-à-dire dans votre application ou votre script. Le serveur Postgres n'a pas besoin de savoir dans quel fichier vous copiez, il crache simplement les données et le client les place quelque part.

La syntaxe sous-jacente à cette commande est la commande _COPY TO STDOUT_, et des outils graphiques tels que pgAdmin l’enveloppent pour vous dans une boîte de dialogue de Nice.

Le psql client en ligne de commande a une "méta-commande" spéciale appelée \copy, qui utilise les mêmes options que le "réel" COPY, mais est exécuté à l'intérieur du client:

_\copy (Select * From foo) To '/tmp/test.csv' With CSV
_

Notez qu'il n'y a pas de fin _;_, car les méta-commandes sont terminées par une nouvelle ligne, contrairement aux commandes SQL.

De les docs :

Ne confondez pas COPY avec l'instruction psql\copy.\copy appelle COPY FROM STDIN ou COPY TO STDOUT, puis extrait/stocke les données dans un fichier accessible au client psql. Ainsi, l'accessibilité aux fichiers et les droits d'accès dépendent du client plutôt que du serveur lorsque\copy est utilisé.

Votre langage de programmation d'application peut également prendre en charge l'envoi ou la récupération de données, mais vous ne pouvez généralement pas utiliser _COPY FROM STDIN_/_TO STDOUT_ dans une instruction SQL standard, car il n'y a aucun moyen de connecter le flux d'entrée/sortie. Le gestionnaire PostgreSQL de PHP ( pas PDO) inclut très basique pg_copy_from et pg_copy_to fonctions qui copient vers/depuis un tableau PHP, qui peuvent ne pas être efficaces pour les grands ensembles de données.

1242
IMSoP

Il y a plusieurs solutions:

1 psql commande

psql -d dbname -t -A -F"," -c "select * from users" > output.csv

Ceci a le gros avantage que vous pouvez l’utiliser via SSH, comme ssh postgres@Host command - vous permettant d’obtenir

2 postgres copy commande

COPY (SELECT * from users) To '/tmp/output.csv' With CSV;

3 psql interactif (ou non)

>psql dbname
psql>\f ','
psql>\a
psql>\o '/tmp/output.csv'
psql>SELECT * from users;
psql>\q

Tous peuvent être utilisés dans des scripts, mais je préfère # 1.

4 pgadmin mais ce n'est pas scriptable.

471
sorin

Dans le terminal (lorsque vous êtes connecté à la base de données), réglez la sortie sur le fichier cvs

1) Réglez le séparateur de champ sur ',':

\f ','

2) Définissez le format de sortie non aligné:

\a

3) Afficher uniquement les tuples:

\t

4) Définir la sortie:

\o '/tmp/yourOutputFile.csv'

5) Exécuter votre requête:

:select * from YOUR_TABLE

6) sortie:

\o

Vous pourrez alors trouver votre fichier csv à cet emplacement:

cd /tmp

Copiez-le à l'aide de la commande scp ou modifiez-le à l'aide de nano:

nano /tmp/yourOutputFile.csv
88
Marcin Wasiluk

Si vous êtes intéressé par tous les colonnes d'un tableau particulier avec les en-têtes, vous pouvez utiliser

COPY table TO '/some_destdir/mycsv.csv' WITH CSV HEADER;

C’est un peu plus simple que

COPY (SELECT * FROM table) TO '/some_destdir/mycsv.csv' WITH CSV HEADER;

qui, à ma connaissance, sont équivalents.

36
benjwadams

Unification des exportations CSV

Cette information n'est pas vraiment bien représentée. Comme c'est la deuxième fois que j'ai besoin de dériver ceci, je vais le mettre ici pour me rappeler si rien d'autre.

La meilleure façon de procéder (pour extraire CSV de postgres) consiste à utiliser la commande COPY ... TO STDOUT. Bien que vous ne vouliez pas le faire de la manière indiquée dans les réponses ici. La manière correcte d'utiliser la commande est la suivante:

COPY (select id, name from groups) TO STDOUT WITH CSV HEADER

Rappelez-vous juste une commande!

C'est génial pour une utilisation sur ssh:

$ ssh psqlserver.example.com 'psql -d mydb "COPY (select id, name from groups) TO STDOUT WITH CSV HEADER"' > groups.csv

C'est génial pour une utilisation dans docker sur ssh:

$ ssh pgserver.example.com 'docker exec -tu postgres postgres psql -d mydb -c "COPY groups TO STDOUT WITH CSV HEADER"' > groups.csv

C'est même génial sur la machine locale:

$ psql -d mydb -c 'COPY groups TO STDOUT WITH CSV HEADER' > groups.csv

Ou à l'intérieur du docker sur la machine locale ?:

docker exec -tu postgres postgres psql -d mydb -c 'COPY groups TO STDOUT WITH CSV HEADER' > groups.csv

Ou sur un cluster kubernetes, dans docker, sur HTTPS ??:

kubectl exec -t postgres-2592991581-ws2td 'psql -d mydb -c "COPY groups TO STDOUT WITH CSV HEADER"' > groups.csv

Tellement polyvalent, beaucoup de virgules!

Est-ce que au moins tu?

Oui je l'ai fait, voici mes notes:

Les COPYses

L'utilisation de /copy exécute efficacement les opérations sur les fichiers, quel que soit le système sur lequel la commande psql est exécutée, comme l'utilisateur qui l'exécute 1 . Si vous vous connectez à un serveur distant, il est simple de copier des fichiers de données sur le système exécutant psql vers/à partir du serveur distant.

COPY exécute les opérations de fichier sur le serveur en tant que compte d'utilisateur du processus backend (_ par défaut postgres), les chemins d'accès et les autorisations de fichier sont vérifiés et appliqués en conséquence. Si vous utilisez TO STDOUT, les vérifications des autorisations de fichiers sont ignorées.

Ces deux options nécessitent le déplacement ultérieur du fichier si psql ne s'exécute pas sur le système sur lequel vous souhaitez que le fichier CSV résultant réside. D'après mon expérience, c'est le cas le plus probable lorsque vous travaillez principalement avec des serveurs distants.

Il est plus complexe de configurer quelque chose comme un tunnel TCP/IP sur ssh vers un système distant pour une sortie CSV simple, mais pour d'autres formats de sortie (binaires), il peut être préférable de /copy sur une connexion tunnelée, en exécutant une psql. De même, pour les importations volumineuses, déplacer le fichier source sur le serveur et utiliser COPY est probablement l'option la plus performante.

Paramètres PSQL

Avec les paramètres psql, vous pouvez formater la sortie comme au format CSV, mais il y a des inconvénients tels que devoir se rappeler de désactiver le pager et de ne pas obtenir les en-têtes:

$ psql -P pager=off -d mydb -t -A -F',' -c 'select * from groups;'
2,Technician,Test 2,,,t,,0,,                                                                                                                                                                   
3,Truck,1,2017-10-02,,t,,0,,                                                                                                                                                                   
4,Truck,2,2017-10-02,,t,,0,,

Autres outils

Non, je veux juste extraire CSV de mon serveur sans compiler et/ou installer un outil.

23
joshperry

J'ai dû utiliser\COPY car j'ai reçu le message d'erreur:

ERROR:  could not open file "/filepath/places.csv" for writing: Permission denied

Alors j'ai utilisé:

\Copy (Select address, Zip  From manjadata) To '/filepath/places.csv' With CSV;

et il fonctionne

22
maudulus

psql peut le faire pour vous:

edd@ron:~$ psql -d beancounter -t -A -F"," \
                -c "select date, symbol, day_close " \
                   "from stockprices where symbol like 'I%' " \
                   "and date >= '2009-10-02'"
2009-10-02,IBM,119.02
2009-10-02,IEF,92.77
2009-10-02,IEV,37.05
2009-10-02,IJH,66.18
2009-10-02,IJR,50.33
2009-10-02,ILF,42.24
2009-10-02,INTC,18.97
2009-10-02,IP,21.39
edd@ron:~$

Voir man psql pour obtenir de l'aide sur les options utilisées ici.

16

Je travaille sur AWS Redshift, qui ne prend pas en charge la fonctionnalité COPY TO.

Mon outil de BI prend en charge les fichiers CSV délimités par des tabulations. J'ai donc utilisé les éléments suivants:

 psql -h dblocation -p port -U user -d dbname -F $'\t' --no-align -c "SELECT * FROM TABLE" > outfile.csv
13
calcsam

Dans pgAdmin III, il existe une option pour exporter dans un fichier à partir de la fenêtre de requête. Dans le menu principal, il s’agit de Query -> Execute to file ou d’un bouton qui fait la même chose (c’est un triangle vert avec une disquette bleue contrairement au triangle vert uni exécutant la requête). Si vous n'exécutez pas la requête à partir de la fenêtre de requête, exécutez la procédure suggérée par IMSoP et utilisez la commande copy.

11
Amanda Nyren

La nouvelle version - psql 12 - supportera --csv.

psql - devel

- csv

Bascule en mode de sortie CSV (valeurs séparées par des virgules). Cela équivaut à \pset format csv .


csv_fieldsep

Spécifie le séparateur de champ à utiliser dans le format de sortie CSV. Si le caractère séparateur apparaît dans la valeur d'un champ, celui-ci est placé entre guillemets, conformément aux règles CSV standard. La valeur par défaut est une virgule.

Usage:

psql -c "SELECT * FROM pg_catalog.pg_tables" --csv  postgres

psql -c "SELECT * FROM pg_catalog.pg_tables" --csv -P csv_fieldsep='^'  postgres

psql -c "SELECT * FROM pg_catalog.pg_tables" --csv  postgres > output.csv
10
Lukasz Szozda

J'ai écrit un petit outil appelé psql2csv qui encapsule le modèle _COPY query TO STDOUT_, ce qui donne un fichier CSV correct. Son interface est similaire à psql.

_psql2csv [OPTIONS] < QUERY
psql2csv [OPTIONS] QUERY
_

La requête est supposée être le contenu de STDIN, s'il est présent, ou le dernier argument. Tous les autres arguments sont transmis à psql à l'exception de ceux-ci:

_-h, --help           show help, then exit
--encoding=ENCODING  use a different encoding than UTF8 (Excel likes LATIN1)
--no-header          do not output a header
_
8
fphilipe

J'ai essayé plusieurs solutions, mais peu d'entre elles ont été en mesure de me fournir le fichier CSV souhaité avec les détails de l'en-tête.

Voici ce qui a fonctionné pour moi.

psql -d dbame -U username \
  -c "COPY ( SELECT * FROM TABLE ) TO STDOUT WITH CSV HEADER " > \
  OUTPUT_CSV_FILE.csv
7
pyAddict

Si vous avez une requête plus longue et que vous aimez utiliser psql, placez votre requête dans un fichier et utilisez la commande suivante:

psql -d my_db_name -t -A -F";" -f input-file.sql -o output-file.csv
5
Andres Kull

Pour télécharger un fichier CSV avec des noms de colonne en tant que HEADER, utilisez cette commande:

Copy (Select * From tableName) To '/tmp/fileName.csv' With CSV HEADER;
3
murli

JackDB , un client de base de données dans votre navigateur Web, rend cela très facile. Surtout si vous êtes sur Heroku.

Il vous permet de vous connecter à des bases de données distantes et d'exécuter des requêtes SQL sur celles-ci.

Source jackdb-heroku http://static.jackdb.com/assets/img/blog/jackdb-heroku-oauth-connect.gif


Une fois votre base de données connectée, vous pouvez exécuter une requête et exporter au format CSV ou TXT (voir en bas à droite).


jackdb-export

Remarque: Je ne suis aucunement affilié à JackDB. J'utilise actuellement leurs services gratuits et pense que c'est un excellent produit.

1
Dennis

Je recommande fortement DataGrip , une base de données IDE de JetBrains. Vous pouvez exporter une requête SQL dans un fichier CSV , et configurer facilement le tunneling SSH. Lorsque la documentation fait référence à "jeu de résultats", ils désignent le résultat renvoyé par une requête SQL dans la console.

Je ne suis pas associé à DataGrip, j'adore le produit!

0
skeller88