PostgreSQLでの部分データ移行
開発環境から本番環境へデータベースを移行する場合など、PostgreSQL では pg_dump でダンプし psql で読み込む(pg_dumpのダンプファイルは SQL文なので、正確には実行)という事を行うと思います。
移行するデータが全体なら pg_dump、 テーブル単位なら pg_dump -t TABLE でダンプできますが、
「あるテーブルのある条件にあてはまるものだけ」という場合は pg_dump では出来ません。
こんな時、PostgreSQL がバージョン8以降なら COPY 文の query 指定が便利です。
SQL> COPY (SELECT * FROM sample_table WHERE id > 10000) TO '/tmp/sample_dump';
のようなSQLを実行すると /tmp/sample_dump に 条件に合ったデータが書かれるので、エディターやスクリプト言語で
先頭に
COPY "sample_table" FROM stdin;
終わりに
\.
を追加すれば、psql で読み込めるようになります。
しかし、 PostgreSQL 7.X では COPY 文の query 指定が出来ないので 簡単なプログラムを書いてみました。
諸事情で Perl です。
use strict; use Pg; my $table = "sample_table"; my $cond = "id > 10000"; my $db = Pg::connectdb("dbname=sample_db user=sample_user"); die "Can't connect to DB " . $db->errorMessage unless ($db->status == PGRES_CONNECTION_OK); my $result = $db->exec("select * from $table where $cond"); die "Select error " . $db->errorMessage unless ($result->resultStatus == PGRES_TUPLES_OK); print "COPY \"$table\" FROM stdin;\n"; while (my @row = $result->fetchrow) { print join("\t", map{defined($_) ? $_ : '\N'} @row) . "\n"; } print "\\.\n";
COPY文のデータ形式は NULL を \N で表すところが特殊なくらいで、あとは文字列としてみた値をタブ区切りで並べれば良いので PostgreSQL の外部形式(?) としては 扱い易いと思います :-)
.