DBD::SQLiteとprepare
ついでに、今回ひっかかっていたところ。
DBD::SQLite 1.12では、こういうスクリプトを実行すると、最後に「closing dbh with active statement handles」という警告が出る。要するに一度も実行されないステートメントハンドルは、finishしてもActiveのまま残ってしまう。
use strict; use warnings; use DBI; unlink 'test.db'; my $db = DBI->connect('dbi:SQLite:test.db'); $db->do('CREATE TABLE test (data TEXT)'); my $sql = 'INSERT INTO test (data) VALUES (?)'; my $st = $db->prepare($sql); my @items = (); $st->execute($_) for @items; $st->finish; # undef $st; $db->disconnect;
1.13の場合は最後の undef $st; を有効にすると警告が消えるんですが、いずれにしてもbuggyなので、いま書いているスクリプトではとりあえず
my $st; my @items = (); for (@items) { $st = $db->prepare($sql) unless $st; $st->execute($_); } $st->finish if $st;
という感じに修正。
そういうところに気を遣いたくないときは
my @items = (); for (@items) { $db->do($sql, undef, $_); }
と書けば警告は出ませんが、もちろん大量にINSERTするときには倍以上遅くなるのを覚悟するべし、と。
あと、上では省略していますが、もちろんSQLiteで大量のデータをINSERTするときはトランザクションを使わないと10倍以上遅くなることもあるというのは有名な話。
ついでに、数万数十万のデータを一度のトランザクションでINSERTしようとするとこれまた激しく重くなるので、適度なところでcommitをはさんだ方がよいというのはPODにも書いてある通り。