[ トップ | 一覧 | 更新履歴 ]

DBI.pm

PerlPackageModules

汎用的なDBとのインターフェース

DBI.pm

DBとのインターフェイスに使います。

行のデータの扱いがhash変数で扱うことができ、複数行ならhashへの参照の配列で扱うことになりますが、 これのおかげでとてもシンプルにコードを書けます。 自動であれ、手製であれ、アクセサいちいち作るようなばかげたことをやる必要もない。 postgreSQLを使ってるので、DBD::Pg.pmも入れてます。

接続

DBI.pmは、オブジェクトを作ってアクセスするというより、ハンドラを使ってアクセスするイメージだけど、実際はどっちも同じこと、ってことが分かります。

new()がないけど、connect()でDBアクセスのインスタンスが出来上がり、 disconnect()でリリースする考えていいようです。 ここでは、メソッドの戻り値を見てエラー処理を行うコードは入れないことにします (論点がかすんでしまうので)。 実際コードを書くときは、エラー処理を行わなくてはなりません。 postgreSQLを使っている場合、

    use     DBI;
    my      $dbh;
    $dbh = DBI->connect('dbi:Pg:dbname=testdb','[user]','[passwd]',{AutoCommit=>0});

上のように文字列リテラルで渡してもいいし、変数で渡してもいい。

connect()のパラメータは、どんなDB(DBD::xxxxx.pm)を使っていても順番とその意味は同じ。ただし、内容が異なる場合があります。特に第1パラメータは使うDBDにより形式が決まってるのでDBDの方のmanualを参照して下さい。postgreSQLならDBD::Pg.pm を参照。DB名までこの第1パラメータで指定します。第2パラメータがDBのユーザ名、第3引数がそのDBユーザのパスワード、第4パラメータはオプション指定の hashへの参照を渡します。 (ここでは無名ハッシュを作って渡しています)

よく見かけるコードは、環境の情報を保持するpackageなんかを用意して、その中にこのパラメータを配列にして渡す場合が多いようです。

    @arg_db = ('dbi:Pg:dbname=testdb','[user]','[passwd]',{AutoCommit=>0});
    ...
    $dbh = DBI->connect(@arg_db);

@arg_dbを別パッケージ(別ファイル)で設定し、変更、管理しやすくするのが狙い。 配列がリストに展開されて引数になって渡されます。

オプションのAutoCommitは、トランザクションtransaction処理をbeginなどのQuery使って、明示的commit(),rollback()メソッドを呼び出す場合は0、毎回勝手にcommitして欲しいときは1を指定します。

他にいくつかオプションあると思いますが、DBDによりサポートしてる、してないってのがあるのでperldocで確認して下さい。

クエリー

DBの典型的な処理、SELECT文とその他INSERT,UPDATE,DELETE文の実行のしかたを書きます。

SELECT

SELECTは、成功したか失敗したかの結果以外に、その選択結果が重要で、それがどのように表現されるかが肝心なところです。1行だったり複数行だったり。 SELECT文以外は成功したか失敗したかだけです。なので2つに分けて説明します。

    CREATE TABLE master_user(
        uid     varchar(32) PRIMARY KEY,
        uname   varchar(64),
    );

というテーブルがあるとします。

このテーブルからuidをKeyに、その該当する行のデータを取得する場合を書きます。

$dbhにconnect()メソッドで取得したハンドラが入ってるとすると、

問題あり

    $user_id = 'yaino';
    ...
    $query = qq{
        SELECT  uid, uname
        FROM    master_user
        WHERE   uid = '$user_id'
    };
    $sth = dbh->prepare($query);
    $sth->execute();  # 実行
    if($sth->rows() != 1){  # 該当する行数
         # エラー処理
    }
    $rhash = $sth->fetchrow_hashref();
    %hash = {%{$rhash}};
    $sth->finish();
    ...
    $uname  = $hash{uname};
    $uid    = $hash{uid};

qqは""で囲んだのと同じ効果があります。なので、$user_idは、その変数の値が展開されます。実際は$queryを引数で受け取るsubroutineを作って処理するでしょうけど。このやりかただと、bindでコードの再利用ができないんで不利だし、エスケープしなければならない文字があります。マルチバイト文字を問題なく使えるかわからん。

改善

    $query = qq{
        SELECT  uid, uname
        FROM    master_user
        WHERE   uid = ?
    };
    $sth = dbh->prepare($query);
    $sth->execute($user_id);  # 実行

実際はこちらの方法でやってください。先の方が分かりやすくていいので、実験のとき などは記述することがありますが、運用すると問題がでてきます。

下のやり方のとき、可変部を?で表し、複数あるときはその順番でexecute()のパラメータに渡します。 「?」は、どのような型であっても「'」で囲む必要はありません。 prepare()メソッドはステートメントハンドル$sthを返します (変数名はなんでもいいですが)。 uidがユニークであるならば、1件のみか、あるいは見つからないというこになります。 fetchは配列の参照を受け取るメソッドもありますが、私は好んでfetchrow_hashref()を使います。SELECTしたカラムの名前とその値がペアでhashになるからです。 prepare()からfinish()まで、SQLを変えて何回でも実行できます。

結果が複数ある場合(該当行が複数ある場合)、 rows()の数だけfetchを繰り返してデータを取り出します。

    $row = $sth->rows(); # COUNT(*)
    while($row){
    $rhash = $sth->fetchrow_hashref();
         my  %hash = {%$rhash};
         push @array, \%hash;
         $row--;
    }
    $sth->finish();

こんなふうに、hashへの参照を配列に入れて結果を保持しています。自分がやっている 方法はこの方法ですが、methodも豊富にそろっているところなので、最適な方法を選んで ください。

ただし、大量な該当行があるときはリソースを食いつぶすため、1行づつ処理するように するか、SELECTにLIMITを付けるなどして対応しなけらばなりません。データの質 に対して処理を変える必要があります。

SELECT以外

fetch()系methodを呼ばないだけです。 あとはSELECT同じで、SQLをprepare()に渡し、ステートメントハンドルを受けて、execute()でbind変数を渡してSQLを実行して finish()しておしまい。

切断

切断の前にcommit(),やrollback()を呼び出し、あるいはAutoCommit=1であればやらなくてもいいですし、デフォルトのの動作にまかせてもいい。

DBハンドルで行います。

    $dbh->commit();
    $dbh->disconnect();


PerlPackageModules


GzuGzu (WikiWikiWeb descendant) ver 1.00 pre2
このページはGzuGzuで作成されました.
yaino.com