Vill du ha den resulterande filen på servern eller på klienten?
Serversidan
Om du vill ha något enkelt att återanvända eller automatisera kan du använda Postgresqls inbyggda COPY-kommando. t.ex.
Copy (Select * From foo) To '/tmp/test.csv' With CSV DELIMITER ',' HEADER;
Det här tillvägagångssättet körs helt på fjärrservern - den kan inte skriva till din lokala dator. Den måste också köras som en Postgres "superanvändare" (normalt kallad "root") eftersom Postgres inte kan stoppa den från att göra elaka saker med den maskinens lokala filsystem.
Det betyder faktiskt inte att du måste vara ansluten som en superanvändare (att automatisera det skulle vara en säkerhetsrisk av ett annat slag), eftersom du kan använda SECURITY DEFINER
alternativet för att CREATE FUNCTION
för att skapa en funktion som körs som om du vore en superanvändare .
Den avgörande delen är att din funktion är där för att utföra ytterligare kontroller, inte bara kringgå säkerheten - så du kan skriva en funktion som exporterar exakt den data du behöver, eller så kan du skriva något som kan acceptera olika alternativ så länge de träffa en strikt vitlista. Du måste kontrollera två saker:
- Vilka filer ska användaren få läsa/skriva på disk? Detta kan till exempel vara en viss katalog och filnamnet kan behöva ha ett lämpligt prefix eller tillägg.
- Vilka tabeller ska användaren kunna läsa/skriva i databasen? Detta skulle normalt definieras av
GRANT
s i databasen, men funktionen körs nu som en superanvändare, så tabeller som normalt skulle vara "out of bounds" kommer att vara helt tillgängliga. Du vill förmodligen inte låta någon anropa din funktion och lägga till rader i slutet av din "användare"-tabell...
Jag har skrivit ett blogginlägg som utvidgar detta tillvägagångssätt, inklusive några exempel på funktioner som exporterar (eller importerar) filer och tabeller som uppfyller strikta villkor.
Kundsidan
Den andra metoden är att göra filhanteringen på klientsidan , det vill säga i din ansökan eller manus. Postgres-servern behöver inte veta vilken fil du kopierar till, den spottar bara ut data och klienten lägger den någonstans.
Den underliggande syntaxen för detta är COPY TO STDOUT
kommando, och grafiska verktyg som pgAdmin kommer att linda in det åt dig i en trevlig dialog.
psql
kommandoradsklient har ett speciellt "metakommando" som heter \copy
, som har samma alternativ som den "riktiga" COPY
, men körs inuti klienten:
\copy (Select * From foo) To '/tmp/test.csv' With CSV
Observera att det inte finns någon avslutande ;
, eftersom metakommandon avslutas av newline, till skillnad från SQL-kommandon.
Från dokumenten:
Blanda inte ihop COPY med psql-instruktionen \copy. \copy anropar COPY FROM STDIN eller COPY TO STDOUT och hämtar/lagrar sedan data i en fil som är tillgänglig för psql-klienten. Filtillgänglighet och åtkomsträttigheter beror alltså på klienten snarare än servern när \copy används.
Ditt applikationsprogrammeringsspråk kan har också stöd för att pusha eller hämta data, men du kan i allmänhet inte använda COPY FROM STDIN
/TO STDOUT
inom en standard SQL-sats, eftersom det inte finns något sätt att koppla in-/utgångsströmmen. PHPs PostgreSQL-hanterare (inte PDO) innehåller mycket grundläggande pg_copy_from
och pg_copy_to
funktioner som kopierar till/från en PHP-array, vilket kanske inte är effektivt för stora datamängder.