Chcete výsledný soubor na serveru nebo na klientovi?
Na straně serveru
Pokud chcete něco snadno znovu použít nebo automatizovat, můžete použít vestavěný příkaz COPY Postgresql. např.
Copy (Select * From foo) To '/tmp/test.csv' With CSV DELIMITER ',' HEADER;
Tento přístup běží výhradně na vzdáleném serveru - nemůže zapisovat do vašeho místního PC. Musí být také provozován jako „superuser“ Postgresu (normálně nazývaný „root“), protože Postgres nemůže zabránit tomu, aby dělal ošklivé věci s místním souborovým systémem tohoto počítače.
To ve skutečnosti neznamená, že musíte být připojeni jako superuživatel (automatizace by představovala bezpečnostní riziko jiného druhu), protože můžete použít SECURITY DEFINER
možnost CREATE FUNCTION
vytvořit funkci, která běží, jako byste byli superuživatel .
Rozhodující je, že vaše funkce slouží k provádění dalších kontrol, nejen k obcházení zabezpečení – takže byste mohli napsat funkci, která exportuje přesná data, která potřebujete, nebo můžete napsat něco, co může přijímat různé možnosti, pokud jsou splnit přísný whitelist. Musíte zkontrolovat dvě věci:
- Které soubory mělo by být uživateli povoleno číst/zapisovat na disk? Může to být například konkrétní adresář a název souboru může mít vhodnou předponu nebo příponu.
- Které tabulky měl by uživatel umět číst/zapisovat do databáze? To by normálně bylo definováno
GRANT
s v databázi, ale funkce nyní běží jako superuživatel, takže tabulky, které by normálně byly „mimo hranice“, budou plně přístupné. Pravděpodobně nechcete nechat někoho, aby vyvolal vaši funkci a přidal řádky na konec vaší tabulky „uživatelé“…
Napsal jsem blogový příspěvek rozšiřující tento přístup, včetně některých příkladů funkcí, které exportují (nebo importují) soubory a tabulky splňující přísné podmínky.
Na straně klienta
Druhým přístupem je zpracování souborů na straně klienta , tedy ve vaší aplikaci nebo skriptu. Server Postgres nepotřebuje vědět, do jakého souboru kopírujete, prostě data vyplivne a klient je někam uloží.
Základní syntaxí je COPY TO STDOUT
a grafické nástroje jako pgAdmin to zabalí do pěkného dialogu.
psql
klient příkazového řádku má speciální "metapříkaz" nazvaný \copy
, který má všechny stejné možnosti jako "skutečný" COPY
, ale je spuštěn uvnitř klienta:
\copy (Select * From foo) To '/tmp/test.csv' With CSV
Všimněte si, že neexistuje žádná koncovka ;
, protože meta-příkazy jsou na rozdíl od SQL příkazů ukončeny novým řádkem.
Z dokumentů:
Nezaměňujte COPY s instrukcí psql \copy. \copy vyvolá COPY FROM STDIN nebo COPY TO STDOUT a poté načte/uloží data do souboru přístupného klientovi psql. Přístupnost k souborům a přístupová práva tedy při použití \copy závisí spíše na klientovi než na serveru.
Váš aplikační programovací jazyk může mají také podporu pro odesílání nebo načítání dat, ale obecně nemůžete použít COPY FROM STDIN
/TO STDOUT
ve standardním příkazu SQL, protože neexistuje způsob připojení vstupního/výstupního toku. PHP PostgreSQL handler (ne PDO) zahrnuje velmi základní pg_copy_from
a pg_copy_to
funkce, které kopírují do/z pole PHP, což nemusí být efektivní pro velké soubory dat.