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.
Voulez-vous le fichier résultant sur le serveur ou sur le client?
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:
GRANT
s 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.
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.
Il y a plusieurs solutions:
psql
commandepsql -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
copy
commandeCOPY (SELECT * from users) To '/tmp/output.csv' With CSV;
>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.
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
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.
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
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!
Oui je l'ai fait, voici mes notes:
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.
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,,
Non, je veux juste extraire CSV de mon serveur sans compiler et/ou installer un outil.
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
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.
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
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.
La nouvelle version - psql 12 - supportera --csv
.
- 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
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
_
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
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
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;
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).
Remarque: Je ne suis aucunement affilié à JackDB. J'utilise actuellement leurs services gratuits et pense que c'est un excellent produit.
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!