[SQLiteメモ][perlメモ]SQLiteで一つのコネクションで複数のデータベースファイルを扱うには?
普通はひとつのデータベースに対して一つのコネクションで接続を行ってデータベース(以下DB)を制御します。一つのDBのなかには複数のテーブルがあってSQLを使って目的のデータを抽出します。一つのDBの中に複数のテーブルがあった方がリレーションするのには都合がいいからです。SQLiteを使っていると一つのDBが一つのファイルになるのですが、私の場合、DBファイルが大きくなるとパフォーマンスが悪くなったり、万が一DBファイルが破損したときに被害が最小限にする為に、リレーショナルする事がないと思われるテーブルは別ファイルにしたりします。
しかし、別DBファイルにしたのにリレーションする必要が出てくる場合があります。大抵の場合考えが甘かった時ですがw。
そういう場合一つのコネクションで二つのDBを開くことになるのですが、そのやり方です。
ATTACHコマンドを使います。
ATTACH [DATABASE] データベースファイルパス AS データベース名
◇参考:SQLite が認識する SQL – Third impact
◇参考:気の向くままに・・・: SQLiteで複数DBへの同時接続
◇参考:sqlite – openbooth
◇参考:SQLite Query Language: ATTACH DATABASE
perl言語からDBI経由で扱う場合下の様にすればよさそうですが、「cannot attach database within transaction」というエラーになります。訳すと、「トランザクションの中でデータベースをアタッチできないよ」ということになります。
#!/usr/local/bin/perl
use strict;
use warnings;
use DBI;
my $hDB = DBI->connect("dbi:SQLite:dbname="test01.db","","",{PrintError=>0,AutoCommit=>0});
unless($hDB){
die $DBI::errstr;
}
my $ATTACH_SQL = "attach database ‘test02.db’ as test02";
my $hst = $hDB->do($ATTACH_SQL);
unless($hst){
my $errstr = $hDB->errstr;
undef $hst;
$hDB->disconnect;
die $errstr;
}
(以下通常のデータベースの処理)
ちょっとしたコツが必要になります。トランザクション中はATTACH DATABASEできないのだから、トランザクション中じゃないときにアタッチすればいいわけで、一旦トランザクションを終わらせてからATTACH(アタッチ)して、ATTACH(アタッチ)後にトランザクションを開始してあげればいいことになります。なので下の様な感じのソースになります。
#!/usr/local/bin/perl
use strict;
use warnings;
use DBI;
my $hDB = DBI->connect("dbi:SQLite:dbname="test01.db","","",{PrintError=>0,AutoCommit=>0});
unless($hDB){
die $DBI::errstr;
}
$hDB->do(‘END’); #トランザクションを一旦終わらせる
my $ATTACH_SQL = "attach database ‘test02.db’ as test02";
my $hst = $hDB->do($ATTACH_SQL);
unless($hst){
my $errstr = $hDB->errstr;
undef $hst;
$hDB->disconnect;
die $errstr;
}
$hDB->do(‘BEGIN’); #トランザクションを開始する
(以下通常のデータベースの処理)
◇参考:Neverwinter Nights: SQLite 3.3.6 ATTACH command