Vil du have den resulterende fil på serveren eller på klienten?
Serversiden
Hvis du vil have noget nemt at genbruge eller automatisere, kan du bruge Postgresqls indbyggede COPY-kommando. f.eks.
Copy (Select * From foo) To '/tmp/test.csv' With CSV DELIMITER ',' HEADER;
Denne tilgang kører udelukkende på fjernserveren - den kan ikke skrive til din lokale pc. Den skal også køres som en Postgres "superbruger" (normalt kaldet "root"), fordi Postgres ikke kan stoppe den med at gøre grimme ting med maskinens lokale filsystem.
Det betyder faktisk ikke, at du skal være tilsluttet som en superbruger (automatisering af det ville være en sikkerhedsrisiko af en anden art), for du kan bruge SECURITY DEFINER
mulighed for at CREATE FUNCTION
at lave en funktion, der kører som om du var en superbruger .
Den afgørende del er, at din funktion er der for at udføre yderligere kontroller, ikke bare omgå sikkerheden - så du kan skrive en funktion, som eksporterer præcis de data, du har brug for, eller du kan skrive noget, der kan acceptere forskellige muligheder, så længe de møde en streng hvidliste. Du skal tjekke to ting:
- Hvilke filer skal brugeren have lov til at læse/skrive på disk? Dette kan for eksempel være en bestemt mappe, og filnavnet skal muligvis have et passende præfiks eller udvidelse.
- Hvilke tabeller skal brugeren kunne læse/skrive i databasen? Dette ville normalt være defineret af
GRANT
s i databasen, men funktionen kører nu som en superbruger, så tabeller, som normalt ville være "out of bounds", vil være fuldt tilgængelige. Du vil sandsynligvis ikke lade nogen kalde din funktion og tilføje rækker i slutningen af din "bruger"-tabel...
Jeg har skrevet et blogindlæg, der udvider denne tilgang, herunder nogle eksempler på funktioner, der eksporterer (eller importerer) filer og tabeller, der opfylder strenge betingelser.
Kundeside
Den anden tilgang er at gøre filhåndteringen på klientsiden , dvs. i din ansøgning eller script. Postgres-serveren behøver ikke at vide, hvilken fil du kopierer til, den spytter bare dataene ud, og klienten placerer dem et sted.
Den underliggende syntaks for dette er COPY TO STDOUT
kommando, og grafiske værktøjer som pgAdmin vil indpakke det for dig i en fin dialog.
psql
kommandolinjeklient har en speciel "meta-kommando" kaldet \copy
, som tager alle de samme muligheder som den "rigtige" COPY
, men køres inde i klienten:
\copy (Select * From foo) To '/tmp/test.csv' With CSV
Bemærk, at der ikke er nogen afsluttende ;
, fordi meta-kommandoer afsluttes af newline, i modsætning til SQL-kommandoer.
Fra dokumenterne:
Forveksle ikke COPY med psql-instruktionen \copy. \copy kalder COPY FROM STDIN eller COPY TO STDOUT og henter/lagrer derefter dataene i en fil, der er tilgængelig for psql-klienten. Filtilgængelighed og adgangsrettigheder afhænger således af klienten frem for serveren, når \copy bruges.
Dit applikationsprogrammeringssprog kan har også understøttelse til at skubbe eller hente dataene, men du kan generelt ikke bruge COPY FROM STDIN
/TO STDOUT
inden for en standard SQL-sætning, fordi der ikke er nogen måde at forbinde input/output-strømmen. PHPs PostgreSQL-handler (ikke PDO) inkluderer meget grundlæggende pg_copy_from
og pg_copy_to
funktioner, der kopierer til/fra et PHP-array, hvilket muligvis ikke er effektivt for store datasæt.