トランザクション
トランザクションは、データベースへの関連する一連の変更が、基本な単位で行われること保証することにより、エラーとデータベース障害から守ります。
このセクションはトランザクションをサポートし、AutoCommit
がオフになっている、データベースにあてはまります。各種のデータベースに対するAutoCommit
の使い方の詳細についてはAutoCommit
を参照してください。
Perl
アプリケーションで強力なトランザクションを実現する方法は、RaiseError
とevel{...}
を使うことをお勧めします(これはevel "..."
よりとても速く動きます)。
$dbh->{AutoCommit} = 0; # 可能であれば、トランザクションを有効にします $dbh->{RaiseError} = 1; eval { foo(...) # INSERTやUPDATEを含む bar(...) # 多くの処理を baz(...) # ここでします。 $dbh->commit; # ここまで来たらコミットします。 }; if ($@) { warn "Transaction aborted because $@"; $dbh->rollback; # undo the incomplete changes # 他のアプリケーションの後片付けの処理をここに入れます }
RaiseError
属性が設定されていなければ、DBI
呼び出しは手動でエラーのチェックをする必要があります。通常は以下のようにします。
$h->method(@args) or die $h->errstr;
RaiseError
を設定すると、そのハンドルや、その子供のハンドルで呼び出されるDBIメ
ソッドが失敗すると、DBI
は自動的に死にます(die
) 。そのため各メソッド呼び出しの戻り値をいちいちチェックする必要がなくなります。詳細についてはRaiseError
を参照してください。
eval
による方法の大きな利点は、アプリケーション内部のいかなる理由で、どのような処理で死んでも(die
)、トランザクションが適切にロールバックされることにあります。$h->{RaiseError}
属性を使う大きな利点は、すべてのDBI
呼び出しが自動的にチェックされることにあります。
commit
やrollback
を呼び出した後、多くのドライバは同じデータベース・ハンドルの子供で以前はアクティブだったSELECT
ステートメント・ハンドルからの取り出しをさせてくれません。これを避ける方法は、データベースに2回接続し、1つの接続をSELECT
ストートメントのために使うことです。
BLOB/LONG/Memoフィールドの扱い
多くのデータベースは、非常に長い文字列や大量のバイナリデータを一つのフィールドに保持するために、BLOB
、long
や似たデータ型をサポートします。いくつかのデータベースは、長さ2,000,000,000バイト以上の可変長のlong
値をサポートします。
long
やバイナリの値を挿入する場合、INSERT
ステートメントの最大のサイズに制限があったり、quote
メソッドがバイナリデータに対処できないので、プレースホルダを使用してください。詳しくはプレースホルダとバインド値を参照してください。
単純な例
データをSELECT
しフェッチする
my $dbh = DBI->connect("dbi:DriverName:db_name", $user,$password) or die "Can't connect to $data_source:$DBI::errstr"; my $sth = $dbh->prepare( "SELECT name, phone FROM mytelbook") or die "Can't prepare statement: $DBI::errstr"; my $rc = $sth->execute or die "Can't execute statement: $DBI::errstr"; print "Query will return $sth->{NUM_OF_FIELDS} fields.\n\n"; print "Field names: @{ $sth->{NAME} }\n"; while (($name, $phone) = $sth->fetchrow_array) { print "$name: $phone\n"; } die $sth->errstr if $sth->err; $dbh->disconnect;
ファイルからあるデータを挿入します(この例は各呼び出しをチェックする必要があることを回避するためにRaiseError
を使用します) 。
my $dbh = DBI->connect("dbi:DriverName:db_name", $user, $password, { RaiseError => 1, AutoCommit => 0 }); my $sth = $dbh->prepare( q{ INSERT INTO table (name, phone) VALUES (?, ?) }); open FH, "<phone.csv" or die "Unable to open phone.csv:$!"; while (<FH>) { chop; my ($name, $phone) = split /,/; $sth->execute($name, $phone); } close FH; $dbh->commit; $dbh->disconnect; #フェッチされたNULL(未定義の値)を空の文字列に変換すること: while($row = $sth->fetchrow_arrayref) { foreach (@$row) { $_ = '' unless defined } print "@$row\n"; }
これらの例で使用されているq{}
スタイルの引用は、SQL
ステートメントの中で使用されるかもしれない引用とぶつかることを回避します。文字列に変数を差し挟みたければ、qq{...}
演算子のようにダブルクォートを使用してください。
デバッグ
trace
メソッドに加えて、Perl
を始める前にDBI_TRACE
環境変数をセットすることにより、同じトレース情報を有効にすることができます。
UNIX
ライクのシステムにおいては、シェルを使用して、単一のコマンドでこれを容易に行うことができます。
DBI_TRACE=2 perl your_test_script.pl
DBI_TRACE
が数値でない値に設定される場合、ファイル名であると仮定され、トレースレベルを2に設定して、すべてのトレース出力はそのファイルに追加され
ます。
詳細はtrace
メソッドを参照してください。