Tips集DBI/DBDの使い方この文章は、perlでcgi等のプログラムができ、SQLの基本的な使い方を知っているひとを対象に書かれています。DBI/DBDモジュールを利用するには、perl5のオブジェクト指向(風)プログラミングの知識もある程度以上は必要です。DBI/DBDDBI/DBDとは、perlとデータベースの間をとりもってくれる汎用インターフェイスです。DBIモジュールとDBDモジュールからできており、DBDモジュールは、各データベースごとに存在します。プログラマは、DBIモジュールのルールにしたがってプログラミングすることで、どのようなデータベースにも、同じようにアクセスするプログラムを書くことができます。ここでは、DBD/pg(PostgreSQL用DBDモジュール)を使った例を提示しますが、基本的には、どのようなDB相手でも同様のことができます。DBIのオフィシャルページhttp://dbi.symbolstone.org/この文章はDBI1.14をベースに書かれています。現在のDBIのバージョンは1.18です。manをインストールしていないなら、manコマンドで内容を見ればよいでしょう。./DBI.3基本的な流れDBI/DBDを使ってperlからDBにアクセスする場合、おおまかには以下のような流れになります。以外モジュール読み込みDB接続ステートメントの準備ステートメントの実行DB切断selectモジュール読み込みDB接続ステートメントの準備ステートメントの実行{データの取り出し}*nDB切断selectの場合は、DBから複数レコードのデータを受け取ることになるので、やや複雑な処理を行う必要があります。ステートメントとは、データベースに渡されるSQL文のことです。基本的なパターンで必要になるオブジェクトやメソッドの解説です。上記の流れと対応しています。DB接続とデータベースハンドル(connect:DBIクラスメソッド)データベースハンドルとは、データベースとの接続を表すオブジェクトです。DBの接続パスワードのようにして接続(connect)します。connectは、データベースハンドルオブジェクトへのリファレンスを返します。以後は、データベースハンドルオブジェクト(ここでは$dbh)を使ってDBにアクセスします。SQLの準備とステートメントハンドル(prepare:データベースハンドルメソッド)ステートメントハンドルとは、準備された特定のSQL文を表すオブジェクトです。connect済みのデータベースハンドルのようにして、ステートメント(SQL文)を準備(prepare)します。prepareは、ステートメントハンドルオブジェクトへのリファレンスを返します。準備だけでは何も起こらず、準備されたステートメントを実行(execute)することで、SQLが実行されます。このとき、SQLの最後にセミコロンをつけてやる必要はありません。ステートメントの実行(execute:ステートメントハンドルメソッド)準備されたステートメントハンドルに対して、executeメソッドを発行してやることで、そのSQLが実行されます。prepareされたステートメントハンドルこのようにしてステートメントは実行されます。正常に実行された場合、executeはtrueを返し、エラーの場合はundefを返します。select文でないステートメントを実行した場合、executeは影響を受けたレコード数を返します。レコード数が0の場合は0E0、レコード数が不明の場合は-1を返します。select文の場合、executeするだけでは、データを取り出す準備ができただけです。その後、$sthに対して、fetchを実行してやる必要があります。selectされたデータの取り出し(fetch:ステートメントハンドルメソッド)executeされたステートメントハンドル(select文)に対して、fetchメソッドを発行することで、1レコードずつのデータを取り出すことができます。executeされたステートメントハンドルこれを実行すると、1レコードのデータが取り出され、そのレコードのデータを持った配列のリファレンスを返します。実行するたびに、新しいレコードのデータが返され、もうレコードがなければundefを返します。fetchは、fetchrow_arrayrefの別名です。connect済みのデータベースハンドルデータベースとの接続を破棄します。通常、プログラムの終了時に実行されます。覚えておくべき便利なメソッド基本的な使い方はあくまでも基本的な使い方です。DBIには、より使いやすく、便利なメソッドが多くあります。ここでは、覚えておくと便利なものについて抜粋して解説します。ハンドル共通メソッドDBIクラス、データベースハンドル、ステートメントハンドル、全てに共通して存在するメソッドです。errstr最後に呼び出されたメソッドについて、データベースが返すエラー文字列を返します。$sth->errstr;主に、上記のように使います。CGIで使う場合は、dieの変わりに、エラーをhtml出力するサブルーチン等を用いるとよいでしょう。dieとevalを組み合わせるのも有効です。データベースハンドルメソッドdoいきなりステートメントを実行します。実行したいSQL文ステートメントをprepareし、executeします。doは影響を受けたレコード数を返します。レコード数が0の場合は0E0、レコード数が不明の場合は-1を返します。データを受け取れないので、select文では使う意味がありません。doは、insert、update、delete等を実行するのにとても便利です。selectall_arrayrefselectの結果を配列のリファレンスで返します。実行したいSQL文ステートメントをprepareし、executeし、全てのレコードについてfetch(fetchall_arryref)します。selectall_arrayrefは、1レコードぶんのデータが入った配列のリファレンスが全件分入っている配列のリファレンスを返します。要するに、2次元配列を返してきます。$ary_ref->[$rows][$cols];のように使います。全てのデータを配列にできるので非常に便利です。これだけ知っていれば、とりあえずselect文を使うことができる。プレースホルダとバインド同じような内容で、パラメータだけが違うようなSQLを何度も実行しなければならないようなとき、その度にprepare、executeを行うのは効率がよくありません。そこで、prepare時には明確な値を与えずにprepareし、execute時にその値を与えてやるという方法があります。テーブルに複数のデータをinsertする場合、たとえば、以下のように書くことができます。$sth->execute(@bind_values);}こうすれば、登録するデータ量が多くても、prepareは1回で済むので、おそらくプログラムは格段に早くなります。プレースホルダ、後からそれに結び付けられる値をバインド値といいます。ここで、1つ覚えておくとよいことがあります。通常、文字列リテラルをSQLで使う場合、シングルクォートで囲ってやる必要があります。バインド値として指定する場合には、それを考える必要はありません。プレースホルダを使うことで、文字列のクォート等の手間を省くことができるわけです。@bind_values);のように、プレースホルダとバインド値を使うことができます。通常DBI/DBDのドライバは、AutoCommit設定になっており、データベースに対して行った変更は自動的に反映されます。トランザクションを制御するには、AutoCommitをオフにし、commitやrollbackを使う必要があります。AutoCommit(データベースハンドルプロパティ)boolean(真/偽)型のプロパティであり、そのデータベースハンドルについて、現在のAutoCommitの状況を表しています。...;のように使います。デフォルトは1(真)です。トランザクションを制御する場合は0(偽)を設定します。commit(データベースハンドルメソッド)コメットさんにちょっと似ています。データベースに対する変更を確定させたいときに呼びます。$dbh->commit;これによって、一連の変更がDBに反映されます。rollback(データベースハンドルメソッド)データベースに対する変更を元に戻したいときに呼びます。$dbh->rollback;これによって、一連の変更がDBに反映されません。その他RaiseError(共通プロパティ)boolean(真/偽)型で、継承されるプロパティです。トランザクションと直接には関係しませんが、組み合わせて使うと便利です。同様の処理を行います。エラーメッセージを出して死ぬわけです。これをeval{}でトラップして以下のように使うと便利です。ここまで来たらコミットします。info@ash.jp。