PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

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

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

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. ex.

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

Cette approche s'exécute entièrement sur le serveur distant - il ne peut pas écrire sur votre PC local. Il doit également être exécuté en tant que "superutilisateur" Postgres (normalement appelé "root") car Postgres ne peut pas l'empêcher de faire des choses désagréables avec le système de fichiers local de cette machine.

Cela ne signifie pas que vous devez être connecté en tant que superutilisateur (l'automatisation serait un risque de sécurité d'un autre type), car vous pouvez utiliser le SECURITY DEFINER option 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 éléments :

  1. Quels fichiers l'utilisateur doit-il être autorisé à lire/écrire sur le disque ? Il peut s'agir d'un répertoire particulier, par exemple, et le nom de fichier peut avoir un préfixe ou une extension appropriée.
  2. Quels tableaux l'utilisateur doit-il pouvoir lire/écrire dans la base de données ? Ceci serait normalement défini par GRANT s dans la base de données, mais la fonction s'exécute maintenant en tant que superutilisateur, de sorte que 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 table "users"...

J'ai écrit un article de blog développant cette approche, y compris quelques exemples de fonctions qui exportent (ou importent) des fichiers et des tables répondant à des conditions strictes.

Côté client

L'autre approche consiste à faire la gestion des fichiers 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 pour cela est le COPY TO STDOUT commande, et des outils graphiques comme pgAdmin l'envelopperont pour vous dans une jolie boîte de dialogue.

Le psql client en ligne de commande a une "méta-commande" spéciale appelée \copy , qui prend toutes les mêmes options que le "vrai" 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 se terminent par une nouvelle ligne, contrairement aux commandes SQL.

À partir de la documentation :

Ne confondez pas COPY avec l'instruction psql \copy. \copy invoque COPY FROM STDIN ou COPY TO STDOUT, puis récupère/stocke les données dans un fichier accessible au client psql. Ainsi, l'accessibilité des 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 ont également un support pour pousser ou récupérer les 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 pg_copy_from très basique et pg_copy_to fonctions qui copient vers/depuis un tableau PHP, ce qui peut ne pas être efficace pour les grands ensembles de données.