受け入れられた回答のソリューションはサーバー上でのみ機能し、クエリを実行するユーザーがこの SO 回答で説明されているようにファイルを読み取る権限を持つ場合にのみ機能します。
それ以外の場合、より柔軟なアプローチは、SQL の COPY
を置き換えることです。 psql
を使用したコマンド \copy
と呼ばれる の「メタコマンド」 これは、「実際の」COPY とすべて同じオプションを取りますが、クライアント内で実行されます (;
は必要ありません)。 最後に):
psql -c "\copy tbname FROM '/tmp/the_file.csv' delimiter '|' csv"
ドキュメントによると、\copy
コマンド:
フロントエンド (クライアント) コピーを実行します。これは SQL COPY コマンドを実行する操作ですが、サーバーが指定されたファイルを読み書きする代わりに、psql がファイルを読み書きし、サーバーとローカル ファイル システムの間でデータをルーティングします。これは、ファイルのアクセシビリティと権限は、サーバーではなくローカル ユーザーのものであり、SQL スーパーユーザー権限は必要ないことを意味します。
さらに、 the_file.csv
の場合 最初の行にヘッダーが含まれており、 header
を追加することで認識できます 上記のコマンドの最後に:
psql -c "\copy tbname FROM '/tmp/the_file.csv' delimiter '|' csv header"
The PostgreSQL Documentation (II. PostgreSQL Client Applications - psql) に記載されているように、コマンドを psql
に渡すことができます (PostgreSQL インタラクティブ ターミナル) スイッチ -c
を使用 .オプションは次のとおりです。
1、クライアント側 CSV:\copy
メタコマンド
SQL COPY
を実行します コマンドですが、ファイルはクライアントで読み取られ、コンテンツはサーバーにルーティングされます。
psql -c "\copy tbname FROM '/tmp/the_file.csv' delimiter '|' csv"
(この回答で最初に言及されたクライアント側のオプション)
2.サーバー側 CSV:SQL COPY
コマンド
サーバー上のファイルを読み取ります (現在のユーザーは必要な権限を持っている必要があります):
psql -c "COPY tbname FROM '/tmp/the_file.csv' delimiter '|' csv;"
サーバー上のファイルを読み取るために必要な DB ロール:
<ブロック引用>
COPY
ファイルまたはコマンドに名前を付けることができるのは、データベースのスーパーユーザーまたはデフォルトのロールの 1 つを付与されたユーザーのみですpg_read_server_files
、 pg_write_server_files
、またはpg_execute_server_program
また、PostgreSQL サーバー プロセスがファイルにアクセスできる必要があります。
最も柔軟な方法は、シェル HERE document
を使用することです 、クエリ内でシェル変数を使用できるようにします。(二重引用符または単一引用符で囲まれている場合でも):
#!/bin/sh
THE_USER=moi
THE_DB=stuff
THE_TABLE=personnel
PSQL=/opt/postgresql/bin/psql
THE_DIR=/tmp
THE_FILE=the_file.csv
${PSQL} -U ${THE_USER} ${THE_DB} <<OMG
COPY ${THE_TABLE} FROM '${THE_DIR}/${THE_FILE}' delimiter '|' csv;
OMG
前の回答を完成させるために、次のことをお勧めします:
psql -d your_dbname --user=db_username -c "COPY tbname FROM '/tmp/the_file.csv' delimiter '|' csv;"