Il comando Postgres client copy (\ copy) non ha accesso a una tabella temporanea?


9

Sto generando un elenco di comandi SQL per esportare alcuni dati che alla fine eseguo usando psql -f. Le query ottengono tutte lo stesso sottoinsieme di dati, quindi ho pensato di fattorizzare le qualifiche e inserire un elenco di ID utente idonei in tabelle temporanee come queste

create temporary table tmp_export_users as (select id from users where ...)

quindi fare riferimento a quello nei miei comandi \ copy come

\copy (select ... from table where user_id in (select id from tmp_export_users)) TO 'filename.csv' WITH CSV HEADER

Questi sono tutti nello stesso file, uno per riga, e li eseguono -f Ottengo l'errore che i comandi di copia non riescono a vedere la tabella temporanea, quindi suppongo che il comando di copia del client non debba effettivamente utilizzare gli stessi postgres sessione come psql.

È corretto? C'è un modo per cambiare quel comportamento?

Risposte:


16

\copy può usare una tabella temporanea.

Prima ho provato e confermato questo con la versione 9.0 dalla riga di comando.
Quindi ho creato un file con meta comando SQL e psql \copyusando più tabelle temporanee. Questo ha funzionato anche per me.

CREATE TEMP TABLE tmp as SELECT * FROM tbl;
\copy (SELECT * FROM tmp JOIN tbl USING (id)) TO '/var/lib/postgres/test1.csv';

Chiamata:

psql -p5432 mydb -f test.sql

Nota il punto e virgola di chiusura, che è facoltativo alla fine di un file (terminato implicitamente), ma richiesto dopo qualsiasi altra istruzione SQL e anche dopo l'ultima se eseguito in psql in modo interattivo.

Normalmente , i meta-comandi psql non possono essere mescolati con SQL sulla stessa riga in un file eseguito per psql -f. Cito il manuale su psql :

L'analisi degli argomenti si interrompe alla fine della riga o quando viene trovata un'altra barra rovesciata non quotata. Una barra rovesciata non quotata viene considerata come l'inizio di un nuovo meta-comando. La sequenza speciale \\(due barre rovesciate) segna la fine degli argomenti e continua a analizzare i comandi SQL, se presenti. In questo modo i comandi SQL e psql possono essere liberamente miscelati su una riga. Ma in ogni caso, gli argomenti di un meta-comando non possono continuare oltre la fine della riga.

Tuttavia, dopo si applicano regole diverse \copy. In sostanza, psql torna automaticamente alla modalità SQL dopo \copyVedi:

Ma hai scritto di avere tutti i comandi su righe separate. Quindi questa non può essere la spiegazione nel tuo caso.


A parte questo, hai considerato di usare COPY(il comando SQL ) invece di \copy(il meta-comando psql )?

Naturalmente, il file di destinazione dovrebbe essere locale al server e non al client in questo caso. E si applicano privilegi di file diversi. Il manuale :

I file nominati in un COPYcomando vengono letti o scritti direttamente dal server, non dall'applicazione client. Pertanto, devono risiedere o essere accessibili al computer del server di database, non al client. Devono essere accessibili e leggibili o scrivibili dall'utente PostgreSQL (l'ID utente utilizzato dal server), non dal client.


copy viene eseguito come utente postgres, \ copy esegue il wrapping di copy per scrivere su std out e reindirizzare al file a cui lo si invia. Puoi anche chiamare psql, usare \ o per inviare l'output a un file e quindi eseguire una copia su stdout per ottenere un effetto simile.
Scott Marlowe,

Per essere sicuro ho eseguito il test nella mia risposta con un superutente (postgres) e un utente fittizio. Entrambi lavorano per me. Stessi risultati su v8.4.
Erwin Brandstetter,

1
Sì, se l'utente unix postgres può accedere a cose come / tmp dipende da cose come se SELinux è installato o meno e se lo fa uscire dalla sua scatola. \ Copy o copy to stdout sono sicuramente i due modi più affidabili per usare copy.
Scott Marlowe,

1
Grazie per le risposte a tutti. Sembra che ho trascurato di terminare la riga che ha creato una tabella temporanea con un punto e virgola, quindi non è stato creato. Funziona come previsto ora
jkebinger
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.