Comanda Postgres client copy (\ copy) nu are ' acces la un tabel temporar?

Generez o listă de comenzi SQL pentru a exporta unele date pe care le rulez în cele din urmă folosind psql -f. Toate interogările obțin același subset de date, așa că m-am gândit că voi „descompune calificările și voi pune o listă de id-uri de utilizator eligibile într-un tabel temporar ca așa

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

apoi să mă refer la asta în \ copy comenzi cum ar fi

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

Acestea sunt toate în același fișier, câte una pe fiecare linie și le rulează – dacă primesc eroarea pe care o pot comanda copierea ” Nu văd tabelul temporar, așa că presupun că comanda de copiere client nu trebuie să utilizeze de fapt aceeași sesiune postgres ca psql.

Este corect? Există o modalitate de a schimba acest comportament?

Răspuns

\copy poate utiliza un tabel temporar.

Mai întâi am testat și confirmat acest lucru cu versiunea 9.0 la linia de comandă.
Apoi am creat un fișier cu comanda SQL și psql meta \copy folosind mai multe tabele temporare. Asta a funcționat și pentru mine.

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

Apel:

psql -p5432 mydb -f test.sql 

Rețineți terminarea punct și virgulă, care este opțional la sfârșitul unui fișier (terminat implicit), dar necesar după orice altă instrucțiune SQL și, de asemenea, după ultima, dacă este executată în psql interactiv.

În mod normal , meta-comenzile psql nu pot fi amestecate cu SQL pe aceeași linie într-un fișier executat per psql -f. Citez manualul de pe psql :

Analiza pentru argumente se oprește la sfârșitul anului linia sau când se găsește o altă bară inversă necotată. O bară inversă necotată este luată ca începutul unei noi meta-comenzi. Secvența specială \\ (două bare oblice inversă) marchează sfârșitul argumentelor și continuă analizarea comenzilor SQL, dacă există. În acest fel, comenzile SQL și psql pot fi amestecate în mod liber pe o linie. Dar, în orice caz, argumentele unei meta-comenzi nu pot continua dincolo de sfârșitul liniei.

Se aplică reguli diferite după \copy, totuși. În esență, psql revine automat la modul SQL după \copy Vedeți:

Dar ați scris că aveți toate comenzile pe linii separate. Deci, aceasta nu poate fi explicația în cazul dvs.


Toate acestea deoparte, v-ați gândit să folosiți COPY (comanda SQL ) în loc de \copy ( meta-comanda psql )?

Desigur, fișierul țintă ar trebui să fie local la server nu clientul în acest caz. Și se aplică diferite privilegii de fișier. Manualul :

Fișiere denumite într-un COPY comanda este citită sau scrisă direct de server, nu de aplicația client. Prin urmare, trebuie să locuiască sau să fie accesibile pentru computerul serverului de baze de date, nu pentru client. Acestea trebuie să fie accesibile și lizibile sau scrise de către utilizatorul PostgreSQL (ID-ul de utilizator pe care îl rulează serverul), nu clientul.

Comentarii

  • copia rulează ca utilizator postgres, \ copy înfășoară copierea pentru a scrie în std out și pentru a fi redirecționat către fișierul către care îl trimiteți. De asemenea, puteți apela psql, utilizați \ o pentru a trimite ieșirea către un fișier și apoi puteți rula o copie pe stdout pentru a obține un efect similar.
  • Pentru a fi sigur că am efectuat testul în răspunsul meu cu un superutilizator (postgres ) și un utilizator fals. Ambele lucrează pentru mine. Aceleași rezultate la v8.4.
  • Da, dacă utilizatorul postgres unix poate accesa sau nu lucruri precum / tmp depinde de lucruri precum dacă SELinux este sau nu instalat și dacă îl lasă să iasă din cutie. \ Copy sau copy to stdout sunt cu siguranță cele două modalități mai fiabile de a folosi copy.
  • Vă mulțumim pentru răspunsuri tuturor. Se pare că am neglijat să termin linia care a creat o tabelă temporară cu punct și virgulă, așa că nu a fost creată '. Funcționează așa cum era de așteptat acum

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *