Generuję listę poleceń SQL w celu wyeksportowania niektórych danych, które ostatecznie uruchamiam za pomocą psql -f. Wszystkie zapytania otrzymują ten sam podzbiór danych, więc pomyślałem, że „rozważyłem kwalifikacje i umieściłem listę kwalifikujących się identyfikatorów użytkowników w tymczasowych tabelach, takich jak ta”
create temporary table tmp_export_users as (select id from users where ...)
, a następnie odnieść się do tego w moim \ kopiuj polecenia, takie jak
\copy (select ... from table where user_id in (select id from tmp_export_users)) TO "filename.csv" WITH CSV HEADER
Wszystkie są w tym samym pliku, po jednym w każdym wierszu i uruchamiają je – jeśli pojawi się błąd, który może spowodować polecenie kopiowania ” nie widzę tymczasowej tabeli, więc zgaduję, że polecenie kopiowania klienta nie może w rzeczywistości używać tej samej sesji postgres co psql.
Czy to prawda? Czy istnieje sposób na zmianę tego zachowania?
Odpowiedź
\copy
może używać tabeli tymczasowej.
Najpierw przetestowałem i potwierdziłem to w wersji 9.0 w wierszu poleceń.
Następnie utworzyłem plik z poleceniem meta SQL i psql \copy
używając wiele tabel tymczasowych. U mnie też to zadziałało.
CREATE TEMP TABLE tmp as SELECT * FROM tbl; \copy (SELECT * FROM tmp JOIN tbl USING (id)) TO "/var/lib/postgres/test1.csv";
Zadzwoń:
psql -p5432 mydb -f test.sql
Zwróć uwagę na zakończenie średnik, który jest opcjonalny na końcu pliku (zakończony niejawnie), ale wymagany po każdej innej instrukcji SQL, a także po ostatniej, jeśli jest wykonywany w psql interaktywnie.
Zwykle , psql meta-polecenia nie mogą być mieszane z SQL w tej samej linii w pliku wykonanym na psql -f
. Cytuję podręcznik na psql :
Analiza argumentów zatrzymuje się na końcu wiersz lub gdy zostanie znaleziony inny niecytowany ukośnik odwrotny. Niecytowany ukośnik odwrotny jest traktowany jako początek nowego polecenia meta. Specjalna sekwencja
\\
(dwa ukośniki odwrotne) oznacza koniec argumentów i kontynuuje analizowanie poleceń SQL, jeśli takie istnieją. W ten sposób polecenia SQL i psql mogą być dowolnie mieszane w linii. W każdym razie argumenty meta-polecenia nie mogą być kontynuowane poza końcem wiersza.
Różne reguły mają zastosowanie po \copy
. Zasadniczo psql automatycznie przełącza się z powrotem do trybu SQL po \copy
Zobacz:
Ale napisałeś, że masz wszystkie polecenia w osobnych wierszach. Więc to nie może być wyjaśnienie w Twoim przypadku.
Pomijając to wszystko, czy rozważałeś użycie COPY
( polecenie SQL ) zamiast \copy
( psql meta-polecenie )?
Oczywiście plik docelowy musiałby być lokalny dla serwera , a nie klient w tym przypadku. Obowiązują różne uprawnienia do plików. Podręcznik :
Pliki nazwane w
COPY
są odczytywane lub zapisywane bezpośrednio przez serwer, a nie przez aplikację kliencką. Dlatego muszą znajdować się na serwerze bazy danych lub być dla niego dostępne, a nie klient. Muszą być dostępne dla użytkownika PostgreSQL (identyfikator użytkownika, na którym działa serwer), a nie dla klienta, które mogą być do odczytu lub zapisu.
Komentarze
- kopiowanie działa jako użytkownik postgres, \ copy zawija kopię w celu zapisu na standardowe wyjście i zostaje przekierowana do pliku, do którego ją wyślesz. Możesz również zadzwonić do psql, użyć \ o, aby wysłać wyjście do pliku, a następnie uruchomić kopię na standardowe wyjście, aby uzyskać podobny efekt.
- Aby upewnić się, że przeprowadziłem test w mojej odpowiedzi z superużytkownikiem (postgres ) i fikcyjny użytkownik. Obie działają dla mnie. Te same wyniki w wersji 8.4.
- Tak, to, czy użytkownik postgres unix może uzyskać dostęp do takich rzeczy, jak / tmp, zależy od rzeczy, takich jak to, czy SELinux jest zainstalowany, czy nie, i czy pozwala na to po wyjęciu z pudełka. \ Copy lub copy to stdout to zdecydowanie dwa bardziej niezawodne sposoby użycia copy.
- Dziękuję wszystkim za odpowiedzi. Wygląda na to, że zapomniałem zakończyć średnikiem wiersza, który utworzył tabelę tymczasową, więc nie ' nie został utworzony. Działa zgodnie z oczekiwaniami teraz