Heeft de postgres-clientkopie (\ copy) -opdracht geen ' toegang tot een tijdelijke tabel?

Ik genereer een lijst met SQL-opdrachten om enkele gegevens te exporteren die ik uiteindelijk uitvoer met psql -f. De zoekopdrachten krijgen allemaal dezelfde subset van gegevens, dus ik dacht dat ik “de kwalificaties zou ontbinden en een lijst met in aanmerking komende gebruikers-IDs in tijdelijke tabellen zou plaatsen, zoals deze

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

verwijs daar dan naar terug in mijn \ kopieeropdrachten zoals

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

Die zitten allemaal in hetzelfde bestand, één per regel, en draaien ze -f ik krijg de foutmelding dat de kopieeropdrachten kunnen ” Ik zie de tijdelijke tabel niet, dus ik vermoed dat het kopieercommando van de client eigenlijk niet dezelfde postgres-sessie als psql mag gebruiken.

Is dat juist? Is er een manier om dat gedrag te veranderen?

Antwoord

\copy kan een tijdelijke tabel gebruiken.

Eerst heb ik dit getest en bevestigd met versie 9.0 op de opdrachtregel.
Vervolgens heb ik een bestand gemaakt met SQL en psql meta-opdracht \copy met meerdere tijdelijke tabellen. Dat werkte ook voor mij.

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

Bellen:

psql -p5432 mydb -f test.sql 

Let op de beëindiging puntkomma, die optioneel is aan het einde van een bestand (impliciet beëindigd), maar vereist na elke andere SQL-instructie en ook na de laatste als deze interactief in psql wordt uitgevoerd.

Normaal kunnen psql-meta-opdrachten niet worden gemengd met SQL op dezelfde regel in een bestand uitgevoerd per psql -f. Ik citeer de handleiding op psql :

Het parseren van argumenten stopt aan het einde van de regel, of wanneer een andere backslash zonder aanhalingstekens wordt gevonden. Een backslash zonder aanhalingstekens wordt genomen als het begin van een nieuwe meta-opdracht. De speciale reeks \\ (twee backslashes) markeert het einde van argumenten en gaat door met het parseren van eventuele SQL-commandos. Op die manier kunnen SQL- en psql-opdrachten vrij op een regel worden gemengd. Maar in elk geval kunnen de argumenten van een meta-commando niet verder gaan dan het einde van de regel.

Andere regels zijn van toepassing na \copy echter. In wezen schakelt psql automatisch terug naar de SQL-modus na \copy Zie:

Maar je schreef dat je alle opdrachten op aparte regels had staan. Dus dat kan in jouw geval niet de verklaring zijn.


Dat alles terzijde, heb je overwogen om COPY (de SQL-opdracht ) in plaats van \copy ( het psql meta-commando )?

Natuurlijk zou het doelbestand lokaal naar de server niet de client in dit geval. En er zijn verschillende bestandsrechten van toepassing. De handleiding :

Bestanden genoemd in een COPY -opdrachten worden rechtstreeks door de server gelezen of geschreven, niet door de clienttoepassing. Daarom moeten ze zich bevinden op of toegankelijk zijn voor de databaseservermachine, niet voor de client. Ze moeten toegankelijk zijn voor en leesbaar of schrijfbaar zijn door de PostgreSQL-gebruiker (de gebruikers-ID waarop de server draait), niet door de client.

Reacties

  • copy wordt uitgevoerd als de postgres-gebruiker, \ copy wraps copy om naar std te schrijven en omgeleid te worden naar het bestand waarnaar je het stuurt. Je kunt ook psql aanroepen, \ o gebruiken om uitvoer naar een bestand te sturen, en dan een kopie naar stdout uitvoeren om een vergelijkbaar effect te krijgen.
  • Om zeker te zijn heb ik de test in mijn antwoord uitgevoerd met een superuser (postgres ) en een dummy-gebruiker. Beiden werken voor mij. Dezelfde resultaten op v8.4.
  • Ja, of de postgres unix-gebruiker al dan niet toegang heeft tot zaken als / tmp hangt af van zaken als of SELinux al dan niet is geïnstalleerd en of het uit zijn doos komt. De \ copy of copy to stdout zijn zeker de twee betrouwbaardere manieren om copy te gebruiken.
  • Bedankt voor de antwoorden, iedereen. Het lijkt erop dat ik heb nagelaten de regel die een tijdelijke tabel heeft gemaakt te beëindigen met een puntkomma, dus ' is niet gemaakt. Nu werken zoals verwacht

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *