
鉄則その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 製作者のメッセージ
ではなかろうか (知らんけど)。


