[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

タグ : , ,