6部 データベース・インタフェイス

データベースハンドル

データベースハンドルは接続したデータベースごとに使うことになるハンドラです。データベースハンドルは、よく使われるメソッドが揃っていますので、すべてが重要といっても過言ではありません。

データベースハンドルメソッド

do

$rc = $dbh->do($statement) || die $dbh->errstr;
$rc = $dbh->do($statement, \%attr) || die $dbh->errstr;
$rv = $dbh->do($statement, \%attr, @bind_values) || ...

SQL文をprepareexecuteし、処理された行数を返します。利用不可などの場合は-1、もしくはundefを返します。

doの使用方法
my $rows = $dbh->do(q{
    DELETE FROM table
}, undef, 'DONE') || die $dbh->errstr;

このメソッドは、prepareしても無効、もしくは繰り返し実行しないSQL文で効果的です。 ステートメント・ハンドルを返さないので、SELECT文では役に立ちません。

doメソッドは、以下の処理と同じことです。

sub do {
    my($dbh, $statement, $attr, @bind_values) = @_;
    my $sth = $dbh->prepare($statement, $attr) or return undef;
    $sth->execute(@bind_values) or return undef;
    my $rows = $sth->rows;
    ($rows == 0) ? "0E0" : $rows; # always return true if no error
}

プレースホルダと@bind_valuesdoメソッドで使うと、$statementの中の変数をクォートする必要がありません。ただし、ステートメントを何度も実行するような場合は、一度だけprepareしてからexecuteを繰り返す方が効果的です。

selectrow_array

@row_ary = $dbh->selectrow_array($statement);
@row_ary = $dbh->selectrow_array($statement, \%attr);
@row_ary = $dbh->selectrow_array($statement, \%attr,
@bind_values);

このメソッドは、prepareexecutefetchrow_arrayをまとめて実行します。リストコンテキストでは最初の行、スカラコンテキストでは最初の行の最初のフィールドを返します。

$statementパラメータは既にprepare済みのステートメント・ハンドルにすることでき、その場合はprepareをスキップします。

いずれかのメソッドでエラーが発生した場合、RaiseErrorが設定されていなければ空のリスト(スカラではundef)を返します。

selectall_arrayref

$ary_ref = $dbh->selectall_arrayref($statement);
$ary_ref = $dbh->selectall_arrayref($statement, \%attr);
$ary_ref = $dbh->selectall_arrayref($statement, \%attr,
@bind_values);

このメソッドはprepareexecutefetchall_arrayrefをまとめて実行します。

$statementパラメータは既にprepare済みのステートメント・ハンドルにすることでき、その場合はprepareをスキップします。

いずれかのメソッドでエラーが発生した場合、RaiseErrorが設定されていなければ空のリスト(スカラではundef)を返します。

selectall_hashref

$ary_ref = $dbh->selectall_hashref($statement);
$ary_ref = $dbh->selectall_hashref($statement, \%attr);
$ary_ref = $dbh->selectall_hashref($statement, \%attr,
@bind_values);

このメソッドは、prepareexecutefetchrow_hashrefをまとめて実行します。返却値は、フィールド名と値のペアを持ったハッシュへのリファレンスです。

$statementパラメータは既にprepare済みのステートメント・ハンドルにすることでき、その場合はprepareをスキップします。何回もステートメントを実行するような場合に効果的です。

fetch以外のメソッドでエラーが発生した場合、RaiseErrorが設定されていなければundefを返します。fetchが失敗し、RaiseErrorが設定されていなければ、それまでに取り出したデータを可能な限り返します。このような場合に備えて$DBI::errをチェックしたほうが良いでしょう。

selectcol_arrayref

$ary_ref = $dbh->selectcol_arrayref($statement);
$ary_ref = $dbh->selectcol_arrayref($statement, \%attr);
$ary_ref = $dbh->selectcol_arrayref($statement, \%attr,
@bind_values);

このメソッドは、prepareexecuteをまとめて実行し、各行からの最初のカラムの値が入った配列へのリファレンスを返します。

$statementパラメータは既にprepare済みのステートメント・ハンドルにすることでき、その場合はprepareをスキップします。何回もステートメントを実行するような場合に効果的です。

fetch以外のメソッドでエラーが発生した場合、RaiseErrorが設定されていなければundefを返します。fetchが失敗し、RaiseErrorが設定されていなければ、それまでに取り出したデータを可能な限り返します。このような場合に備えて$DBI::errをチェックしたほうが良いでしょう。

prepare

$sth = $dbh->prepare($statement) || die $dbh->errstr;
$sth = $dbh->prepare($statement, \%attr) || die $dbh->errstr;

SQL文を実行できるように準備し、ステートメント・ハンドルへのリファレンスを返します。返却値のステートメント・ハンドルはステートメントの属性を取得したり、executeメソッドを起動するために使用できます。prepareを使うとexecuteの実行速度が向上します(ただし、MySQLでは単に文を保存するだけです)。

このメソッドはプレースホルダが使えます。

プレースホルダの使用例
my $sth = $dbh->@prepare("SELECT * FROM mytable WHERE name LIKE ?");
$sth->bind_param(1, 'J%');

ステートメントを準備する概念を持っていないエンジンのドライバは、$sth->executeが呼ばれるまでは、$sth->{NUM_OF_FIELDS}などは返せません。

通常、SQLでは文の終わりにセミコロンなどを使いますが、DBIでは必要ありません。

prepare_cached

$sth = $dbh->prepare_cached($statement) || die $dbh->errstr;
$sth = $dbh->prepare_cached($statement, \%attr) || die $dbh->errstr;

キャッシングを行う点を除いてprepareと同じです。同じパラーメータ値でprepare_cachedを呼び出すと、データベースに接続しないで、キャッシュにある$sthを返します。

このキャッシングは有効ではありますが、問題の原因になりやすいので注意しましょう。現在、キャッシュされている$sthActiveだと警告されます。
CachedKids属性でキャッシュにアクセスすることができます。

commit MySQL非サポート

$rc = $dbh->commit || die $dbh->errstr;

データベースがトランザクションをサポートする場合、データベース変更の中で最も最新の変更をコミットします。 
データベースがトランザクションをサポートし、AutoCommitがオンの場合、commitcommit ineffective with AutoCommit警告を出します。 

rollback MySQL非サポート

$rc = $dbh->rollback || die $dbh->errstr;

データベースがトランザクションをサポートする場合、コミットされていない最も最新の変更をロールバック(取消)します。 
データベースがトランザクションをサポートし、AutoCommitがオンの場合、rollbackrollback ineffective with AutoCommit警告を出します。 

disconnect MySQLでは必要なし

$rc = $dbh->disconnect or warn $dbh->errstr;

データベース・ハンドルをデータベースから切断します。disconnectはプログラムを終了するときにだけ使います。

トランザクションを備えたDBMSは、disconnect実行によって変更を自動的にコミットするものや、変更をロールバックするものなどがあり、統一されていません。AutoCommitを使わないアプリケーションは、disconnectを呼び出す前に、commitまたはrollbackをするべきです。

まだ接続していて、ハンドルへの参照がなくなった場合、DESTROYメソッドによりデータベースは自動的に切断されます。各ドライバへのDESTROYメソッドはコミットされていない変更を元に戻すため、暗黙のうちにrollbackを呼び出します。

Activeなステートメント・ハンドルがあるのに、disconnectを使うと警告を受けます。ステートメント・ハンドルは切断の前に破棄するか、そlれぞれにfinishメソッドを呼び出すべきです。

ping

$rc = $dbh->ping;

合理的で効率的な方法で、データベースサーバーが稼動しているか、接続が正常かを調査します。アプリケーションでこのメソッドを使うことはあまりないでしょう。

現在のデフォルトの実装は、実際には何もせず常に"真"を返します。実際には、それは0 but trueを返します、これは"真"ですがゼロです。これにより返された値が本物なのか単なるデフォルトなのかがわかります。。ドライバはこのメソッドをデータベースのタイプにあったものでこのメソッドを上書きしなければなりません。

使用例としては専門的なApache::DBIモジュールをご覧ください。

table_info primary_key_info primary_key tables type_info_all type_info

実験的に使われているメソッドです。

quote

$sql = $dbh->quote($value);
$sql = $dbh->quote($value, $data_type);

このメソッドは、文字列リテラルをSQL文で使えるように特殊文字をエスケープし、文字列全体をクォートで囲みます。未定義の$value値はNULLとして返されます。

$sql = sprintf "select foo from bar where baz = %s",
$dbh->quote("Don't\n");

quoteは、バイナリデータ、それにシェルのエスケープやメタ文字には対応していません。 また、プレースホルダとバインド値で使われる値についてはquoteする必要ありません。

PAGE TOP


データベースハンドル属性

データベース・ハンドル属性を変更しても、既にあるほかのハンドルの属性には影響を与えません。
ドライバに依存する属性を除いては、決められていない属性を設定、あるいは取得しようとするとエラーが発生します。

$h->{AutoCommit} = ...; # 設定
... = $h->{AutoCommit}; # 読み込み

AutoCommit(ブール) MySQL非サポート

値が"真"であれば、データベースの変更を元に戻すことはできません。"偽"であれば、データベースの変更は自動的にトランザクションのなかに入り、commitまたはrollbackメソッドを使ってコミットあるいはロールバックされなければなりません。

AutoCommitをサポートされていない値に設定しようとすると、致命的なエラーになります。完全なトランザクションを必要とするアプリケーションは、代入される値が
正しいかどうかをチェックすることなしに、 $dbh->{AutoCommit}=0 (またはconnectメソッド
AutoCommitを 0 に設定)とすることができます。

トランザクションを全くサポートしないデータベース

これらのデータベースで、AutoCommitをオフにしようとすると致命的なエラーになります。commitrollbackは、AutoCommitが有効な間は、無効であると警告します。

トランザクションが常に活発なデータベース

AutoCommitがオフの場合、データベースへの変更はcommitされるまで有効になりません。rollbackが呼ばれれば、最後のcommit以降の変更はすべて元に戻されます。
AutoCommitがオンであるば、DBIはまるで、正常終了したデータベース操作の後、自動的にcommit
呼んでいるのと同じように振る舞います。

AutoCommitをオフからオンに返ると、大抵のドライバはcommitします。

トランザクションが明示的に始められなければならないデータベース

これらのデータベースでは、トランザクションが常に有効なデータベースと同じような動作をします。
DBIドライバは、AutoCommitがオフになると、自動的にトランザクションを開始します。そしてcommitrollback.の後、自動的に新しいトランザクションを開始します。

Driver (handle)

ハンドルの親ドライバを保持します。

print $dbh->{Driver}->{Name}, "\n";

Name(文字列)

データベースの名前を保持します。

Statement (文字列, 読み取り専用)

prepareに渡されたステートメント文字列を返します。Statementが有効なケースとしては、RaiseErrorが有効になっていて、例外ハンドラが$@をチェックし、prepareメソッドが失敗したかもしれないと思われるときです。

RowCacheSize(整数)

RowCashSizeの値は、SELECT文に使うローカルな行キャッシュの大きさを示します。行キャッシュが実装されていなければ、RowCashSizeの設定は無視され、undefが返されます。

RowCacheSizeの値

レベル 解説
0以下 各 SELECT
のためにメモリの量に合わせて行をキャッシュします
0 自動的に各 SELECT
に適切なキャッシュサイズを決めます
1 ローカル行キャッシュを使用しません
1以上 この数だけ行をキャッシュします

キャッシュされる行の数×行の最大サイズだけのメモリが必要になるので、必要なだけの値を設定するべきです。また、キャッシュの大きさだけ最初の取得、もしくは次のキャッシュ分を取得するさいに時間がかかるようになります。

RowsInCacheも参照してください。

関連記事