Postgresクライアントのコピー(\ copy)コマンドは一時テーブルにアクセスできませんか?


9

最終的にpsql -fを使用して実行するデータをエクスポートするためのSQLコマンドのリストを生成しています。クエリはすべて同じデータのサブセットを取得するので、資格を考慮に入れて、適格なユーザーIDのリストを一時テーブルにそのように配置すると思いました

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

それから私のような\ copyコマンドでそれをもう一度参照してください

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

それらはすべて同じファイルにあり、1行に1つずつ実行します。-fコピーコマンドが一時テーブルを表示できないというエラーが表示されるので、クライアントのコピーコマンドが実際に同じpostgresを使用してはいけないと思いますpsqlとしてのセッション。

あれは正しいですか?その動作を変更する方法はありますか?

回答:


16

\copy 一時テーブル使用できます。

最初に、コマンドラインでバージョン9.0を使用してこれをテストおよび確認しました。
次に、\copy複数の一時テーブルを使用して、SQLおよびpsqlメタコマンドでファイルを作成しました。それもうまくいきました。

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

コール:

psql -p5432 mydb -f test.sql

ファイルの終わりで暗黙的に終了する終了セミコロンに注意してください。ただし、他のSQLステートメントの後に、またpsqlでインタラクティブに実行する場合は最後のステートメントの後にも必要です。

通常、psqlメタコマンドは、ごとに実行されるファイルの同じ行でSQLと混在させることはできませんpsql -f。私はpsqlマニュアルを引用します

引数の解析は、行の終わり、または引用符で囲まれていない別のバックスラッシュが見つかったときに停止します。引用符で囲まれていないバックスラッシュは、新しいメタコマンドの始まりと見なされます。特別なシーケンス\\(2つの円記号)は、引数の終わりを示し、SQLコマンドがあれば、それを解析し続けます。これにより、SQLコマンドとpsqlコマンドを1行に自由に混在させることができます。しかし、いずれにせよ、メタコマンドの引数は行末を超えて続けることはできません。

ただし、の後に \copyは異なるルールが適用さます。基本的に、psqlは以下のように自動的にSQLモードに戻ります\copy

しかし、すべてのコマンドが別々の行にあると書いています。したがって、それはあなたの場合の説明にはなりません。


さておき、あなたが使用して検討していることのすべてCOPYSQLコマンド)の代わりに、\copypsqlのメタコマンドを)?

もちろん、この場合、ターゲットファイルはクライアントではなくサーバーにローカルである必要があります。また、さまざまなファイル権限が適用されます。マニュアル

COPYコマンドで指定されたファイルは、クライアントアプリケーションではなくサーバーによって直接読み書きされます。したがって、クライアントではなく、データベースサーバーマシンに常駐するか、データベースサーバーマシンからアクセスできる必要があります。それらは、クライアントではなく、PostgreSQLユーザー(サーバーが実行されているユーザーID)からアクセス可能であり、読み取りまたは書き込み可能でなければなりません。


copyはpostgresユーザーとして実行され、\ copyはcopyをラップしてstd outに書き込み、送信先のファイルにリダイレクトされます。また、psqlを呼び出し、\ oを使用して出力をファイルに送信し、次にstdoutへのコピーを実行して同様の効果を得ることができます。
スコットマーロウ

確かに、スーパーユーザー(postgres)とダミーユーザーを使用して、私の答えでテストを実行しました。どちらもうまくいきます。v8.4でも同じ結果になります。
Erwin Brandstetter

1
うん、postgres unixユーザーが/ tmpのようなものにアクセスできるかどうかは、SELinuxがインストールされているかどうか、それがそのまま使えるかどうかに依存します。\ copyまたはcopy to stdoutは、copyを使用するための2つのより信頼できる方法です。
スコットマーロウ

1
皆様のご回答ありがとうございます。一時テーブルを作成する行をセミコロンで終了するのを怠っていたため、作成されませんでした。期待どおりに動作する
jkebinger
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.