所以我一直試圖使用 COPY (SELECT...) TO STDOUT WITH (FORMAT CSV, HEADER) 但是
- PDO::query() 使用 prepare,而 COPY 不支援
- PDO::exec() 不返回結果
- PDO::pgsqlCopyToFile() 不支援額外參數,只支援分隔符號和空值(以及欄位)
但你知道它支援什麼嗎?SQL 注入!
https://github.com/php/php-src/blob/7dfbf4d1b74b5e629f2331261944fa072a92e1cb/ext/pdo_pgsql/pgsql_driver.c#L870
spprintf(&query, 0, "COPY %s TO STDIN WITH DELIMITER E'%c' NULL AS E'%s'", ...
這些都沒有任何跳脫字元,所以你可以這樣呼叫這個方法
<?php
$db->pgsqlCopyToFile("(select * from t1 cross join t2 using (whatever))", '/tmp/test.csv', ',', '\' header--');
?>
而這實際上產生了
COPY (select...) TO STDIN WITH DELIMITER E',' NULL AS E'' header--
它仍然使用本地檔案系統,我可以接受,但至少我不必再為 CSV 標頭煩惱。
如果有人知道更好的方法可以在不將(在我的例子中是巨大的)結果集複製到陣列和 fputcsv() 的情況下做到這一點,我很樂意聽取。而且我已經嘗試了 pg_query 和 pg_copy_to 的所有組合,但都無濟於事。