Jag genererar en lista med SQL-kommandon för att exportera vissa data som jag slutligen kör med psql -f. Frågorna får alla samma delmängd av data, så jag trodde att jag skulle tänka ut kvalifikationerna och lägga en lista över kvalificerade användar-id i tillfälliga tabeller som så
create temporary table tmp_export_users as (select id from users where ...)
och hänvisa tillbaka till det i min \ kopiera kommandon som
\copy (select ... from table where user_id in (select id from tmp_export_users)) TO "filename.csv" WITH CSV HEADER
De finns alla i samma fil, en per rad, och kör dem -f jag får det fel som kopieringskommandona kan ” se den tillfälliga tabellen, så jag antar att kommandot klientkopiering inte får använda samma postgres-session som psql.
Stämmer det? Finns det ett sätt att ändra det beteendet?
Svar
\copy
kan använda en tillfällig tabell.
Först testade jag och bekräftade detta med version 9.0 vid kommandoraden.
Sedan skapade jag en fil med SQL och psql metakommandot \copy
med flera tillfälliga tabeller. Det fungerade också för mig.
CREATE TEMP TABLE tmp as SELECT * FROM tbl; \copy (SELECT * FROM tmp JOIN tbl USING (id)) TO "/var/lib/postgres/test1.csv";
Ring:
psql -p5432 mydb -f test.sql
Observera avslutningen semikolon, som är valfritt i slutet av en fil (avslutas implicit), men krävs efter alla andra SQL-uttalanden och även efter den sista om den körs i psql interaktivt.
Normalt kan , psql metakommandon inte blandas med SQL på samma rad i en fil som körs per psql -f
. Jag citerar manualen på psql :
Analysering av argument slutar i slutet av raden, eller när en annan ociterad snedstreck hittas. Ett obekräftat snedstreck tas som början på ett nytt metakommando. Den speciella sekvensen
\\
(två snedstreck) markerar slutet på argumenten och fortsätter att analysera SQL-kommandon, om några. På så sätt kan SQL- och psql-kommandon blandas fritt på en rad. Men i vilket fall som helst kan argumenten för ett metakommandot inte fortsätta efter slutet av raden.
Olika regler gäller efter \copy
. I huvudsak växlar psql tillbaka till SQL-läge automatiskt efter \copy
Se:
Men du skrev att du hade alla kommandon på separata rader. Så det kan inte vara förklaringen i ditt fall.
Bortsett från det, har du funderat på att använda COPY
( SQL-kommandot ) istället för \copy
( psql metakommandot )?
Naturligtvis måste målfilen vara lokal till servern inte klienten i det här fallet. Och olika filbehörigheter gäller. Manualen :
Filer namngivna i en
COPY
-kommandot läses eller skrivs direkt av servern, inte av klientapplikationen. Därför måste de ligga på eller vara tillgängliga för databasservermaskinen, inte för klienten. De måste vara tillgängliga för och läsbara eller skrivbara av PostgreSQL-användaren (användar-ID servern kör som), inte klienten.
Kommentarer
- kopia körs som postgres-användare, \ copy wraps copy för att skriva ut och omdirigeras till filen du skickar den till. Du kan också ringa psql, använda \ o för att skicka utdata till en fil och sedan köra en kopia till stdout för att få liknande effekt.
- För att vara säker på att jag körde testet i mitt svar med en superanvändare (postgres ) och en dummyanvändare. Båda fungerar för mig. Samma resultat på v8.4.
- Ja, om postgres-unix-användaren kan komma åt saker som / tmp beror på saker som om SELinux är installerat eller inte och om det släpper det ur sin låda. Kopian eller kopian till stdout är definitivt de två mer tillförlitliga sätten att använda kopia.
- Tack för svaren alla. Det verkar som om jag försummat att avsluta raden som skapade en tillfällig tabell med semikolon, så det blev inte '. Fungerar som förväntat nu