DBのデータを自分で作成したプログラムで更新した時に、どうやって検証をするかという内容です。
PostgreSQLにはCOPY文でCSVに出力することが可能なので、出力したCSVを更新前後でdiffりました。
まずはDBの中身はこんな感じ。testという名前のDBに↓の様なデータを入れておきます。
test=# SELECT * FROM test_table; id | name | tel ----+-----------+------------ 1 | yamada | 012345678 2 | takahashi | 123456789 3 | suzuki | 234567890 1 | takeda | 3456789012 (4 rows)
コマンドは、以下、1行だけ。
psql <DB名> -c "COPY <テーブル名> TO '<ファイル名>' CSV --------------------------------------------------- 【例】 [root@Melchior ~]# psql test -c "COPY test_table TO '/tmp/hoge.csv' CSV" COPY 4 [root@Melchior ~]# cat /tmp/hoge.csv 1,yamada,012345678 2,takahashi,123456789 3,suzuki,234567890 4,takeda,3456789012
条件を指定することも出来ます。
[root@Melchior ~]# psql test -c "COPY (SELECT * FROM test_table WHERE id = 1) TO '/tmp/hoge.csv' CSV" COPY 1 [root@Melchior ~]# cat /tmp/hoge.csv 1,yamada,012345678
複数のテーブルがある時に、テーブルによって条件を変えてCSV化する必要があったので簡単なシェルスクリプトを作りました。仕様はこんな感じ。
- 引数に、DB名、テーブルのリスト、出力先のディレクトリを指定。
- テーブルのリストには、テーブル名、WHERE句以降の条件がパイプ区切りで記載。
- 出力するファイル名は<テーブル名>.csvとする。
#!/bin/sh usage() { MESSAGE=$1 echo "Usage: $0 <db name> <db list> <dump dir>" echo " ** $MESSAGE" exit 1 } DB_NAME=$1 DB_LIST=$2 DUMP_DIR=$3 CURDIR=`pwd` DUMP_DIR="$CURDIR/$DUMP_DIR" if [ -z $DB_NAME ]; then usage "DB NAME is empty!" fi if [ -z $DB_LIST ]; then usage "DB LIST is empty!" fi if [ -z $DUMP_DIR ]; then usage "DUMP DIR is empty!" fi if [ ! -f $DB_LIST ]; then usage "DB LIST is not file!" fi if [ ! -d $DUMP_DIR ]; then usage "DUMP DIR is not directory!" fi cat $DB_LIST | while read line do TABLENAME=`echo $line | awk -F'|' '{print $1}'` CONDITION=`echo $line | awk -F'|' '{print $2}'` if [ ! -z "$CONDITION" ]; then psql "$DB_NAME" -c "COPY (SELECT * FROM $TABLENAME WHERE $CONDITION) TO '$DUMP_DIR/$TABLENAME.csv' CSV" else psql "$DB_NAME" -c "COPY $TABLENAME TO '$DUMP_DIR/$TABLENAME.csv' CSV" fi if [ $? -ne 0 ]; then echo "Error occurred" exit 1 fi done
dblist.txtの中身。
test_table|id = 1 test_table2
DBの中身。
test=# select * from test_table; id | name | tel ----+-----------+------------ 1 | yamada | 012345678 2 | takahashi | 123456789 3 | suzuki | 234567890 4 | takeda | 3456789012 (4 行) test=# select * from test_table2; id | name | tel -----+------+----- 100 | aaa | 000 101 | bbb | 111 102 | ccc | 222 (3 行)
以下、実行例。
[root@Melchior ~]# ./db2csv.sh test dblist.txt tmp/ COPY 1 COPY 3 [root@Melchior ~]# [root@Melchior ~]# [root@Melchior ~]# ll tmp/ total 4 -rw-r--r-- 1 pgsql wheel 19 5 17 01:12 test_table.csv -rw-r--r-- 1 pgsql wheel 36 5 17 01:12 test_table2.csv [root@Melchior ~]# [root@Melchior ~]# more tmp/*.csv 1,yamada,012345678 ...skipping... 100,aaa,000 101,bbb,111 102,ccc,222
※作ったコードそのままではありません。
注意
- ファイルのパスは絶対パスでないとダメ。
- ファイルのパスはシングルクオートで囲まないとダメっぽい。特にシェルスクリプトを作る時は注意。
- PostgreSQLのユーザで実行されるため、出力先がPostgreSQLのユーザで書き込めるところでないとダメ。↑の場合、rootでmkdirすると、↓みたいに怒られる。
ERROR: could not open file "/root/tmp/test_table.csv" for writing: Permission denied
今回のシェルスクリプトに関わらず、シェルスクリプトの定石みたいなのは覚えておくと便利だと思います。
(↑のcat してwhileでreadを回すみたいなところ)