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

DBI ステートメント・ハンドル

2009年7月6日


データベースハンドルと同様、もしくはそれ以上に、重要なメソッドが揃っています。できればすべてをマスターするのがベストですが、なかでもbind_paramexecutefetchfetchrow_hashrefbind_columnsは抑えていたほうがよい重要なメソッドです。

ステートメント・ハンドルメソッド

bind_param

$rc = $sth->bind_param($p_num, $bind_value) || die $sth->errstr;
$rv = $sth->bind_param($p_num, $bind_value, \%attr) || ...
$rv = $sth->bind_param($p_num, $bind_value, $bind_type) || ...

bind_paramメソッドは、ステートメント内のプレースホルダに値を割り当てます(DBI::prepare 参照)。

bind_paramの使用方法
$dbh->{RaiseError} = 1; # 各メソッド呼び出しをチェックするようにする
$sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE ?");
$sth->bind_param(1, "John%"); # プレースホルダのインデックスは1から
$sth->execute;
DBI::dump_results($sth);

※いくつかのドライバはプレースホルダをサポートしません。

プレースホルダは1つのスカラ値だけを表わします。そのためこのステートメントで複数の値を期待してもうまく動きません。

\%attrパラメータはプレースホルダが持つべきデータ型を指定するために使われます。

$sth->bind_param(1, $value, { TYPE => SQL_INTEGER });

短縮した方法として、データ型を直接渡すことができます。下記の例は、上記と同じです。

$sth->bind_param(1, $value, SQL_INTEGER);

TYPEは一度bind_param呼び出ししてしまったら変更できません。ドライバ特有の型を指定するために、ドライバがドライバ特有の属性をサポートしていることがあります。
DBIがサポートするSQL型は、SQL_CHARSQL_NUMERICSQL_DECIMALSQL_INTEGERSQL_SMALLINTSQL_FLOATSQL_DOUBLESQL_VARCHARです。対応する方のリストは下記の通り です。

DBI MySQL
SQL_CHAR FIELD_TYPE_CHAR
FIELD_TYPE_DATE
FIELD_TYPE_DATETIME
FIELD_TYPE_NULL
FIELD_TYPE_TIMESTAMP
FIELD_TYPE_TIME
SQL_NUMERIC FIELD_TYPE_LONG
FIELD_TYPE_LONGLONG
FIELD_TYPE_SHORT
SQL_DECIMAL FIELD_TYPE_DECIMAL
SQL_INTEGER FIELD_TYPE_INT24
SQL_SMALLINT FIELD_TYPE_INT24
SQL_FLOAT FIELD_TYPE_FLOAT
SQL_DOUBLE FIELD_TYPE_DOUBLE
SQL_VARCHAR FIELD_TYPE_TINY_BLOB
FIELD_TYPE_MEDIUM_BLOB
FIELD_TYPE_BLOB
FIELD_TYPE_LONG_BLOB
FIELD_TYPE_VAR_STRING
FIELD_TYPE_STRING

bind_param_inout DBD::Oracle専用

$rc = $sth->bind_param_inout($p_num, \$bind_value, $max_len) || die $sth->errstr;
$rv = $sth->bind_param_inout($p_num, \$bind_value, $max_len, \%attr) || ...
$rv = $sth->bind_param_inout($p_num, \$bind_value, $max_len, $bind_type) || ... 

このメソッドはbind_paramのように作用しますが、値がステートメントから(更新された)出力されることを可能にします。ステートメントは通常、ストアドプロシジャへの呼び出しです。 

$bind_valueは実際に使われる変数へのリファレンスとして渡されます。bind_paramとは違い、$bind_value変数はbin_param_inoutが呼ばれたときには読みこまれないことに注意してください。変数の値はexecuteが呼ばれたときに読みこまれます。
パラメータは、$bind_valueの新しい値のために確保される最小限のメモリ量を指定します。もし実際の値が大きすぎてはいらなければ、executeは失敗します。使用する量がわからなければ、返されるもっとも長い値よりも大きな長さを指定しましょう。

execute

$rv = $sth->execute || die $sth->errstr;
$rv = $sth->execute(@bind_values) || die $sth->errstr;

prepare済みのステートメントを実行します。正常終了の場合、行数が 0 の場合でも"真"を返します。失敗したら、undefを返します。
executeは、SELECT文が実行された場合は、問い合わせ結果を返します。SELECT文でなければ、処理の対象となった行数、行数が確認できない場合には -1 を返します。結果は、fetch系のメソッドで取り出すことができます。

executeに引数@bind_valuesを指定すると、そのステートメントを実行する前にbind_paramが呼び出されます。このようにして結び付けられた値は、SQL_VARCHARタイプとして扱われます。

executeの使用方法
# 一般的な使用法
$sth->prepare("SELECT * FROM mytable");
$stf->execute;
# プレースホルダを利用
$sth->prepare("SELECT name FROM mytable WHERE name LIKE ?");
$sth->execute("J%");
# 上記の結果、nameフィールドの値で「J」から始まる行が返される

fetchrow_arrayref/fetch

$ary_ref = $sth->fetch;

データの次の行を取り出し、フィールドの値をもった配列へのリファレンスを返します。NULL値はundefで返されます。$sth->bind_columnsを使っていれば、これがデータを取り出すもっとも早い方法です。
取り出せる列がないか、エラーが発生すると、undefを返します(後で$sth->errをチェックするか、RaiseErrorを使ってください)。 

fetchの使用方法
$sth->execute;
while( my $ref = $sth->fetch ){
    print $ref,"\n";
}

fetchrow_array

@ary = $sth->fetchrow_array;

次のデータ行を取り出し、フィールドの値を持った配列を返します。

fetchrow_hashref

$hash_ref = $sth->fetchrow_hashref;
$hash_ref = $sth->fetchrow_hashref($name);

データの次の行を取り出し、フィールド名と値のペアを持ったハッシュへのリファレンスを返します。NULL値はundefとして返されます。
取り出せる行がないか、エラーが発生すると、undefを返します(後で$sth->errをチェックするか、RaiseErrorを使ってください)。 

オプションの$nameパラメータは、ステートメント・ハンドル属性のnameを指定し、取得するフィールドの名前を示します。デフォルトは"NAME"です。
ハッシュのキーは$sth->{$name}によって返される名前と同じです。複数のフィールドが同じ名前であった場合、返されたハッシュのなかのそれらのフィールドためのエントリはたった1つになります。
fetchrow_hashrefを使うことは、現状ではデータベース間で移植可能ではありません。というのもデータベースが違うと返ってくるフィールド名が大文字、小文字が違うことがあるからです。
fetchrow_hashreffetchfetchrow_arrayほど効率よくありません。

fetchall_arrayref

$tbl_ary_ref = $sth->fetchall_arrayref;
$tbl_ary_ref = $sth->fetchall_arrayref( $slice_array_ref );
$tbl_ary_ref = $sth->fetchall_arrayref( $slice_hash_ref
);

fetchall_arrayrefは、prepareされ、executeされたステートメント・ハンドルから、すべてのデータを取り出し、配列へのリファレンスとして返します。配列の各要素には、返されたレコードへのリファレンスが格納されます。

取り出せる行がないか、エラーが発生すると、undefを返します(後で$sth->errをチェックするか、RaiseErrorを使ってください)。 

ハッシュのリファレンスを渡すと、各行をハッシュのリファレンスで取り出せます。その際、ハッシュのキーには小文字でフィールド名を指定し、値を1に設定します。

各行の先頭のカラムだけを取り出す
$tbl_ary_ref = $sth->fetchall_arrayref([0]);
各行の一番後ろ、その直前の列を取り出す
$tbl_ary_ref = $sth->fetchall_arrayref([-2,-1]);
各行のfooとbarというフィールドだけを取り出す
$tbl_ary_ref = $sth->fetchall_arrayref({ foo=>1, bar=>1 });

最初の2つの例では、配列リファレンスの配列へのリファレンスを返し、最後の例はハッシュ・リファレンスの配列へのリファレンスを返します。

finish MySQL では不要

 $rc = $sth->finish;

もう一度executeされるか、破棄されるまで、このステートメント・ハンドルからは、データが取り出されないことを示します。finishメソッドはあまり必要になることはありませんが、サーバーのリソースを解放させることなど、限られた状況では役に立ちます。

finishメソッドはデータベース接続のトランザクションの状態にはなにも影響を与えません。すぐにステートメント・ハンドルを破棄、または再実行するのであれば、finishを呼ぶ必要はありません。disconnectActive属性も参照してください。

rows

$rv = $sth->rows;

データベース変更コマンドにより最後に処理された行数を返します。不明または使用不能の場合は-1になります。
通常、rowsdoまたはSELECT文以外のexecute、またはSELECT文のすべての行を取り出した後に使用します。それ以外で使用したrowsの返却値は信頼できません。

bind_col

$rc = $sth->bind_col($column_number, \$var_to_bind);
$rc = $sth->bind_col($column_number, \$var_to_bind, \%attr);

SELECT文の出力フィールドにPerlの変数を結び付けます。最初のフィールドの番号は1、2つ目の引数は、ステートメント内にあるフィールドの番号、3つ目はハッシュ属性へのリファンレンスで、省略可能です(DBD::mysqlでは使わない)。なお、フィールド番号は1からカウントされます。失敗するとundefを返します。

使用例はbind_columnsを参照してください。

ドライバ間の移植性を高めるために、 executeの後に実行してください。

bind_paramメソッドは入力変数については同じです。詳細はプレースホルダとバインド値を参照してください。

bind_colの使用方法
$sth->bind_col(1, \$field1, undef);
$sth->bind_col(2, \$field2, undef);
$sth->execute;
while ( $sth->fetch ){
    # $field1と$field2は、出力時に対応するフィールドにバインドされる
    print "Field1:$field1 Field2:$field2 \n";
}

bind_columns

$rc = $sth->bind_columns(\%attr, @list_of_refs_to_vars_to_bind);

SELECT文の各列にbind_colを呼び出します。リファレンスの数がフィールドの数と合っていないと、bind_columnsは失敗します。

ドライバ間の移植性を高めるために、executeの後に実行してください。

bind_columnsの使用方法
$dbh->{RaiseError} = 1; # do this, or check every call for errors
$sth = $dbh->prepare(q{ select region, sales from sales_by_region });
my ($region, $sales);
# Perlの変数を列に結び付ける
# $sth->bind_columns(undef, \($region, $sales));
$sth->execute;
# カラムの結びつけはデータの取り出しで、もっとも効率的な方法
while ($sth->fetch) {
    print "$region: $sales\n";
}

dump_results

$rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh);

ステートメント・ハンドルの内容を出力します。クエリ結果を手早く確認したい場合に便利です。最初の引数はテーブル内の各フィールドの最大長(デフォルトは 35)、2つ目は各行を区切る文字列(デフォルトは"\n")、3つ目は各フィールドを区切る文字列(デフォルトはカンマ( , ))、5つ目はファイルハンドルへのリファレンスで、結果が出力されます(デフォルトはSTDOUT)。失敗はundefを返します。

PAGE TOP

ステートメント・ハンドル属性 

ステートメント・ハンドルの属性は、そのほとんどが読み込み専用です。これらのステートメント・ハンドル属性を変更しても、ほかのハンドルや後で作成されるステートメント・ハンドルには影響しません。

ドライバに依存する属性を除いては、決められていない属性を設定、あるいは取得しようとするとエラーが発生します。

ドライバによっては、$sth->executeが呼ばれるまでは、一部、もしくはすべての属性について正しい値を提供できないものもあります。

NUM_OF_FIELDS(整数、読み出し専用) 

準備したステートメントが返すフィールドの数を返します。SELECT文以外はNUM_OF_FIELDS==0です。

NUM_OF_PARAMS(整数、読み出し専用) 

準備したステートメント中のプレースホルダの数を返します。

NAME(配列リファレンス、読み出し専用)

各フィールドのためにフィールド名の配列へのリファレンスを返します。

print "First column name: $sth->{NAME}->[0]\n";

NAME_lc (配列リファレンス, 読み出し専用)

NAMEと同じです。ただし常に小文字で名前を返します。

NAME_uc (配列レファレンス, 読み出し専用)

NAMEと同じです。ただし常に大文字で名前を返します。

TYPE(配列リファレンス、読み出し専用)

各フィールドに対する整数値の配列へのリファレンスを返します。値はデータ型の対応するフィールドを示します。
使用される値は、国際標準(ANSI X3.135ISO/IEC 9075)に準拠しています。正確に標準のタイプと一致しないドライバ固有の型は、データベースのメーカーによって供給されたODBCドライバと同じ値を返します。ベンダーが公式に登録したプライベートな型番号を含んでいることもあります。

ftp://jerry.ece.umassd.edu/isowg3/dbl/SQL_Registry

ODBCドライバがない場合、ドライバはDBI用に予約されている -9999 ~ -9000 の範囲の型番号が使えます。

 TYPEに対する可能な値は、type_info_allメソッドの出力の中に 、少なくとも1つの要素として入っていなければなりません。

PRECISION(配列リファレンス、読み出し専用)

各カラムに対する整数値の配列への参照を返します。数値以外のカラムでは、カラムの最大長、あるいは定義された長さです。数値のカラムでは、データ型によって使われる意味のある最大桁数を示します(符号文字か小数点の考慮のない)。浮動小数点型(REALFLOATDOUBLE)では、表示サイズはprecisionよりも7文字まで、大きいかもしれません(符号+小数点+Eという文字+符号+2または3桁)。

SCALE(配列リファレンス、読み出し専用)

各カラムに対する整数値の配列へのリファレンスを返します。 NULL(undef)値は、scaleが適用されないことを示します。

NULLABLE(配列リファレンス、読み出し専用) 

各カラムがNULLを許可するかを示す値を、配列へのリファレンスで返します(0=NO/1=YES/2=undef)。 

print "First column may return NULL\n"
    if $sth->{NULLABLE}->[0];

CursorName(文字列、読み出し専用) 

利用可能な場合にステートメント・ハンドルに関連したカーソルの名前を返します。サポートされていないか、利用不可の場合はundefを返します。

Statement (文字列, 読み出し専用)

prepareに渡されたステートメント文字列を返します。

RowsInCache(整数、読み出し専用)

ドライバがSELECT文のためのローカルの列キャッシュをサポートする場合、この属性は、キャッシュの中にフェッチしられていない列の数を保持します。ドライバがしない場合、undefを返します。
詳細はRowCacheSizeデータベースハンドル属性を参照してください。

関連記事

Comment

コメントを残す

メールアドレスが公開されることはありません。

リズムファクトリーはホームページの制作会社です。
ホームページ制作に関するご要望・ご相談はこちらからどうぞ。