こんにちは。新米🍚エンジニアのしげぞうです。
前回は、AWSの社内勉強会に参加したときのことについて書いたのですが、
今回は先日携わった業務で使用したPostgreSQLのCOPYコマンドについて書いてみたいと思います。
COPYコマンドとは
PostgreSQLのCOPY
コマンドは、テーブルとDBサーバ内のファイル間でデータのやり取り(読み込み/書き出し)をするためのコマンドです。
負荷テスト用に大量データを投入する際に利用したり、テキストベースでバックアップを取ったりする際に利用することができます。
ちなみに、pg_dump
コマンドでダンプをスクリプト形式で出力した際は、データ投入部分がCOPY
コマンドで構成されていたりします。
それぞれ、以下のコマンドで実行することができます。
-- データの読み込み。ファイルからテーブルにデータをコピーする。
COPY table_name (column_name [, ...]) FROM '/xxxxx/filename';
-- データの書き出し。テーブルの内容をファイルにコピーする。
COPY table_name TO '/xxxxx/filename';
FROM
,TO
句には、DBサーバ内の絶対パスで対象ファイルを指定します。
ファイルの種類としては、テキスト, CSV, バイナリ形式が利用できますが、CSVでのやり取りが良いかと思います。
また、対象データベースのスーパーユーザで実行する必要があります。
COPY FROM
では実際に、データの取り込みをやってみます。
例えば、こんなテーブルと取り込み用データを準備したとすると、
postgres=# SELECT * FROM test_table;
id | food_name |
----+------------
(0 rows)
=======================================================
=======================================================
$ cat /xxxxx/test_table.csv
id,food_name
1,りんご
2,パン
3,ハンバーグ
下記のコマンドでデータを取り込むことができます。
-- ファイルからデータを取り込む。
-- csvから取り込むので、CSV パラメータを指定。
-- ヘッダーを読み込まないようにするため、HEADER オプションを指定。
COPY test_table (id, food_name) FROM '/xxxxx/test_table.csv' WITH CSV HEADER;
実際にコマンドを流してみると、、
postgres=# COPY test_table (id, food_name) FROM '/xxxxx/test_table.csv' WITH CSV HEADER;
COPY 3
postgres=# SELECT * FROM test_table;
id | food_name
----+-----------
1 | りんご
2 | パン
3 | ハンバーグ
(3 rows)
無事、取り込むことができました。
COPY
コマンドは既存のテーブルにデータを追記していくので、既にレコードが存在していても問題なく取り込むことができます。
$ cat /xxxxx/test_table_add.csv
id,food_name
4,みかん
5,パスタ
6,オムライス
postgres=# COPY test_table (id, food_name) FROM '/xxxxx/test_table_add.csv' WITH CSV HEADER;
COPY 3
postgres=# SELECT * FROM test_table;
id | food_name
----+-----------
1 | りんご
2 | パン
3 | ハンバーグ
4 | みかん
5 | パスタ
6 | オムライス
(6 rows)
COPY TO
データの書き出しをやってみます。今回は、先ほど投入したデータに対してコマンドを実行します。
postgres=# COPY test_table TO '/xxxxx/output1_test_table.csv' WITH CSV HEADER;
COPY 6
$ cat /xxxxx/output1_test_table.csv
id,food_name
1,りんご
2,パン
3,ハンバーグ
4,みかん
5,パスタ
6,オムライス
また、COPY TO
では、テーブル名を指定する代わりに、SELECT文で取得対象を指定することもできます。
postgres=# COPY (SELECT * FROM test_table WHERE id = 4) TO '/xxxxx/output2_test_table.csv' WITH CSV HEADER;
COPY 1
$ cat /xxxxx/output2_test_table.csv
id,food_name
4,みかん
注意事項
\COPY
対象ファイルがDBサーバ内に存在している場合は、COPY
コマンドでデータの読み書きを実行できるのですが、ファイルがDBサーバ内に存在せず、クライアント側に存在する場合はCOPY
コマンドで実行することはできないようです。
(ちなみに私はここでハマりました。。あくまでCOPY
コマンドは、DBサーバ上でファイルを入出力するコマンド。)
クライアント側に読み書き対象ファイルを配置する場合は、\COPY
コマンドで実行することができます。
-- ファイルからデータを取り込む(先頭に¥をつけます)
\COPY test_table (id, food_name) FROM '/xxxxx/test_table.csv' WITH CSV HEADER;
-- ファイルにデータを書き出す(先頭に¥をつけます)
\COPY test_table TO '/xxxxx/bk_test_table.csv' WITH CSV HEADER;
ファイルのパスには、クライアント側のパスを絶対パスで指定します。
また、\COPY
コマンドはスーパーユーザでなくても実行することができます。
文字コード
読み込み対象のCSVファイルの文字コードが、DBの文字コードと一致していない場合は、ENCODING
オプションを指定する必要があります。
-- DBがUTF8、ファイルがSJISの場合。
COPY test_table (id, food_name) FROM '/xxxxx/test_table.csv' encoding 'sjis' WITH CSV HEADER;
ENCODING
オプションを省略した場合は、クライアントの符号化方式の設定が適用されます。
(クライアント符号化方式はSET client_encoding TO
や \encoding
コマンドで変更可能)
最後に
備忘録みたいになりましたが、今回はPostgreSQLのCOPY
コマンドについて書いてみました。
また、気になるPostgreSQLの機能などを見つけたら、書いてみようと思います。
3件のコメント