無精で短気で傲慢なプログラマ

UNIX や web やプログラムの技術的なことを中心に。

perl+DBI プログラムの鉄則 - fetchrow_arrayref を使え

perl+DBI プログラムの鉄則 のつつき。

鉄則その3.

   while ( my $arr_ref = $sth->fetchrow_arrayref ){
      my ($hoge, $fuga) = @$arr_ref;
      ...
   }

SELECT 時は上記のように fetchrow_arrayref を使うこと。そして必ずスカラーに
代入すること。せっかく fetchrow_arrayref を使っていても

   while ( my $arr_ref = $sth->fetchrow_arrayref ){
      print "$$arr_ref[0] $$arr_ref[1]\n";
   }

などと書いては台無しである。配列のインデックスで指定すると取得カラムの
増減に非常に弱い。そしてなりより、$$arr_ref[1] が何を意味するのか
さっぱりわからない。


fetchrow_array は使わない。複数カラムを取得する場合は問題ないが、
1カラムのみ取得する際に

   $sql = "SELECT hoge FROM table1";
   $sth->prapre($sql);
   $sth->execute;
   while ( $hoge = $sth->fetchrow_array ){
      ...
   }

とスカラーコンテキストで fetchrow_array を使ってしまうと問題が
出てくる。もしこのとき hoge が NULL であった場合、fetch 途中にも
かかわらずループが終了してしまうから。

fetchrow_hashref は使わない。

   while ( my $hash_ref = $sth->fetchrow_hashref ){
      print "hoge=[$hash_ref->{hoge}] fuga=[$hash_ref-{fuga}]\n";
   }

と書けるのは便利ではあるが、ハッシュはタイプミス耐性がない。

   print $hash_ref->{hoge};



   print $hash_ref->{moge};

とタイプミスした場合、値は undef になる。しかし DB 内の NULL は、DBI に
おいては undef として扱われるため、タイプミスと NULL の区別がつかない
(exists で調べれば区別はつくが、そんなことをわざわざやる人はほとんど
いない)。

fetchall 系は、最初は教えない。数百万・数千万・数億レコードの相手を
するようになったときに困るから。最終的にオンメモリに置くデータなら
別にかまわないが、それはメモリサイズを直感的に把握できるようになってから。


fetch というメソッドもあるが、これは fetchrow_arrayref の別名となっている。
fetch という短くてタイプしやすいメソッド名の権利を獲得したのは
fetchrow_array でもなく、fetchrow_hashref でもなく、fetchrow_arrayref
なのである。

これこそまさに fetchrow_arrayref を使うべし、という DBI 製作者のメッセージ
ではなかろうか (知らんけど)。
スポンサーサイト

PageTop

コメント


管理者にだけ表示を許可する
 

typo?

参考にさせていただいております。で、何回か見ているうちに気づいたのですが。
最後の一節、fetchは
fetchall_arrayref じゃなくてfetchrow_arrayref のaliasじゃなかったでしたっけ。

もぎゃ | URL | 2006-12-21(Thu)22:44 [編集]


typo でした。fetchall_arrayref -> fetchrow_arrayref に修正いたしました。ご指摘ありがとうございました。

68user | URL | 2006-12-27(Wed)16:24 [編集]


大変勉強させていただきました。
my ($hoge, $fuga) = @arr_ref;
ではなくて
my ($hoge, $fuga) = @$arr_ref;
でしょうか。

gama子 | URL | 2007-04-23(Mon)15:40 [編集]


ご指摘ありがとうございます。いまさらですが修正いたしました。

68user | URL | 2008-02-22(Fri)02:43 [編集]


fetchrow_hashref では、コピペでタイプしなければ間違えないような

while ( my $arr_ref = $sth->fetchrow_arrayref ){
my ($hoge, $fuga) = @$arr_ref;
...
}

では、レコードにundefがあるとif文でかわさないとずれます。
鉄則は、言い過ぎでは?

源さん | URL | 2014-03-11(Tue)11:27 [編集]


> 源さん
3年前にいただいたコメントを、先程承認して表示いたしました。

> レコードにundefがあるとif文でかわさないとずれます。
ずれるとは、どこがどうずれるのでしょうか。試さずに書いてすみません。

68user | URL | 2017-03-15(Wed)18:51 [編集]