Vuoi il file risultante sul server o sul client?
Lato server
Se vuoi qualcosa di facile da riutilizzare o automatizzare, puoi usare il comando COPY integrato di Postgresql. es.
Copy (Select * From foo) To '/tmp/test.csv' With CSV DELIMITER ',' HEADER;
Questo approccio viene eseguito interamente sul server remoto - non può scrivere sul tuo PC locale. Deve anche essere eseguito come un "superutente" Postgres (normalmente chiamato "root") perché Postgres non può impedirgli di fare cose brutte con il filesystem locale di quella macchina.
Ciò in realtà non significa che devi essere connesso come superutente (automatizzare ciò sarebbe un rischio per la sicurezza di diverso tipo), perché puoi usare il SECURITY DEFINER
opzione per CREATE FUNCTION
per creare una funzione che funziona come se fossi un superutente .
La parte cruciale è che la tua funzione è lì per eseguire controlli aggiuntivi, non solo bypassare la sicurezza, quindi potresti scrivere una funzione che esporti i dati esatti di cui hai bisogno, oppure potresti scrivere qualcosa che può accettare varie opzioni purché soddisfare una rigorosa whitelist. Devi controllare due cose:
- Quali file l'utente dovrebbe essere autorizzato a leggere/scrivere su disco? Potrebbe trattarsi di una directory particolare, ad esempio, e il nome del file potrebbe dover avere un prefisso o un'estensione adatti.
- Quali tabelle l'utente dovrebbe essere in grado di leggere/scrivere nel database? Questo sarebbe normalmente definito da
GRANT
s nel database, ma la funzione ora è in esecuzione come superutente, quindi le tabelle che normalmente sarebbero "fuori limite" saranno completamente accessibili. Probabilmente non vuoi permettere a qualcuno di invocare la tua funzione e aggiungere righe alla fine della tua tabella "utenti"...
Ho scritto un post sul blog in cui si espande questo approccio, inclusi alcuni esempi di funzioni che esportano (o importano) file e tabelle che soddisfano condizioni rigorose.
Lato cliente
L'altro approccio consiste nel gestire i file sul lato client , ovvero nell'applicazione o nello script. Il server Postgres non ha bisogno di sapere su quale file stai copiando, sputa semplicemente i dati e il client li mette da qualche parte.
La sintassi sottostante è COPY TO STDOUT
comando e strumenti grafici come pgAdmin lo avvolgeranno in una bella finestra di dialogo.
Il psql
client a riga di comando ha uno speciale "meta-comando" chiamato \copy
, che accetta tutte le stesse opzioni del COPY
"reale". , ma viene eseguito all'interno del client:
\copy (Select * From foo) To '/tmp/test.csv' With CSV
Nota che non ci sono ;
di terminazione , perché i meta-comandi vengono terminati da newline, a differenza dei comandi SQL.
Dai documenti:
Non confondere COPIA con l'istruzione psql \copy. \copy richiama COPY FROM STDIN o COPY TO STDOUT, quindi recupera/memorizza i dati in un file accessibile al client psql. Pertanto, l'accessibilità ai file ei diritti di accesso dipendono dal client piuttosto che dal server quando viene utilizzato \copy.
Il tuo linguaggio di programmazione dell'applicazione può hanno anche il supporto per il push o il recupero dei dati, ma in genere non puoi utilizzare COPY FROM STDIN
/TO STDOUT
all'interno di un'istruzione SQL standard, perché non c'è modo di collegare il flusso di input/output. Il gestore PostgreSQL di PHP (non PDO) include pg_copy_from
molto semplice e pg_copy_to
funzioni che copiano in/da un array PHP, che potrebbero non essere efficienti per set di dati di grandi dimensioni.