sql >> Database >  >> RDS >> PostgreSQL

Sla PL/pgSQL-uitvoer van PostgreSQL op in een CSV-bestand

Wilt u het resulterende bestand op de server of op de client?

Serverzijde

Als u iets wilt dat gemakkelijk opnieuw te gebruiken of te automatiseren is, kunt u het ingebouwde COPY-commando van Postgresql gebruiken. bijv.

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

Deze aanpak draait volledig op de externe server - het kan niet naar uw lokale pc schrijven. Het moet ook worden uitgevoerd als een Postgres "superuser" (normaal gesproken "root" genoemd) omdat Postgres niet kan voorkomen dat het vervelende dingen doet met het lokale bestandssysteem van die machine.

Dat betekent niet dat je als superuser verbonden moet zijn (dat automatiseren zou een ander soort beveiligingsrisico zijn), omdat je de SECURITY DEFINER kunt gebruiken optie om CREATE FUNCTION om een ​​functie te maken die loopt alsof je een supergebruiker bent .

Het cruciale onderdeel is dat uw functie er is om extra controles uit te voeren, niet alleen om de beveiliging te omzeilen - u kunt dus een functie schrijven die de exacte gegevens exporteert die u nodig hebt, of u kunt iets schrijven dat verschillende opties accepteert zolang ze voldoen aan een strikte witte lijst. Je moet twee dingen controleren:

  1. Welke bestanden moet de gebruiker worden toegestaan ​​om op schijf te lezen/schrijven? Dit kan bijvoorbeeld een bepaalde map zijn en de bestandsnaam moet mogelijk een geschikte prefix of extensie hebben.
  2. Welke tafels moet de gebruiker kunnen lezen/schrijven in de database? Dit wordt normaal gesproken gedefinieerd door GRANT s in de database, maar de functie wordt nu uitgevoerd als een superuser, dus tabellen die normaal "buiten de grenzen" zouden zijn, zijn volledig toegankelijk. U wilt waarschijnlijk niet dat iemand uw functie aanroept en rijen toevoegt aan het einde van uw "gebruikers"-tabel...

Ik heb een blogpost geschreven waarin deze benadering wordt uitgebreid, inclusief enkele voorbeelden van functies die bestanden en tabellen exporteren (of importeren) die aan strikte voorwaarden voldoen.

Klantzijde

De andere benadering is om de bestandsverwerking aan de clientzijde uit te voeren , d.w.z. in uw applicatie of script. De Postgres-server hoeft niet te weten naar welk bestand u kopieert, hij spuugt de gegevens gewoon uit en de client plaatst deze ergens.

De onderliggende syntaxis hiervoor is de COPY TO STDOUT commando, en grafische tools zoals pgAdmin zullen het voor je inpakken in een mooi dialoogvenster.

De psql opdrachtregelclient heeft een speciaal "meta-commando" genaamd \copy , die dezelfde opties heeft als de "echte" COPY , maar wordt uitgevoerd in de client:

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

Merk op dat er geen afsluitende ; . is , omdat meta-commando's worden beëindigd door newline, in tegenstelling tot SQL-commando's.

Uit de documenten:

Verwar COPY niet met de psql-instructie \copy. \copy roept COPY FROM STDIN of COPY TO STDOUT aan, en haalt dan de gegevens op in een bestand dat toegankelijk is voor de psql-client. De toegankelijkheid van bestanden en toegangsrechten zijn dus afhankelijk van de client en niet van de server wanneer \copy wordt gebruikt.

De programmeertaal van uw applicatie mag hebben ook ondersteuning voor het pushen of ophalen van de gegevens, maar u kunt in het algemeen geen gebruik maken van COPY FROM STDIN /TO STDOUT binnen een standaard SQL-statement, omdat er geen manier is om de input/output-stroom te verbinden. PHP's PostgreSQL-handler (niet PDO) bevat zeer eenvoudige pg_copy_from en pg_copy_to functies die kopiëren naar/van een PHP-array, wat mogelijk niet efficiënt is voor grote datasets.



  1. FOUT 2002 (HY000):Kan geen verbinding maken met lokale MySQL-server via socket '/var/run/mysqld/mysqld.sock' (2)

  2. Combineer meerdere resultaten in een subquery tot één door komma's gescheiden waarde

  3. Oracle - Een alleen-lezen gebruiker maken

  4. Hoe de ID van de laatst bijgewerkte rij in MySQL te krijgen?