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

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

perl+DBI プログラムの鉄則 - SQL 文の書き方

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

鉄則その4.

  my $sql =
    "SELECT ".
    "   hoge, ".
    "   fuga ".
    "  FROM table1 ".
    " WHERE foo = ?";

SQL 文の可読性を高めるため、必ずインデントを付けること。SQL はプログラムと
データベースの界面である。プログラムが正しくて、なおかつデータベースが正しく
ても、SQL 文が誤っていたら全ては台無しとなる。

しかも SQL 文は多機能なわりに短く書けるので、情報密度が高い (逆に言うと
重要な部分を読み取りづらい)。SQL 文の可読性を高めずして、プログラムの質の
向上はない。

  $dbh->prepare("SELECT hoge, fuga FROM table1 WHERE foo = ?");

などと prepare や execute の引数に直接 SQL 文を書いてはいけない。必ず一度
$sql などの変数に代入しよう。どんなに気をつけても、手で書いた SQL には
大抵ミスがあるものである。一度 SQL に代入しておけば、

  print "$sql\\n";

とすることで print デバッグができる。特に初心者には作業効率の向上に
つながるだろう。なお、「一度変数に代入した方がよい」というのは SQL に
限らずプログラム一般に言えるノウハウである。print (printf) デバッグも
できるし、ソースレベルデバッガを使っている場合でも、どんな値が入って
いるか確認しやすい。


1行につき、項目・条件は 1つだけ書く。
  my $sql =
    "SELECT ".
    "   hoge, fuga ".
    "  FROM table1 ".
    " WHERE foo = ? AND bar = ?";
と 1行に複数項目・複数条件を書かない。理由は可読性の向上に加え、コメントを付け
やすくするため。

  " WHERE NVL(foo, 0) = ?". # ほげ情報が未指定の場合は foo は NULL なので 0 に変換する
  " AND bar = ?";

などと書けるようにする (NVL は NULL なら指定された値に変換する Oracle の
関数。MySQL なら IFNULL。SQL の規格的にこういう関数があるかどうかは知らない)。

もうひとつの理由は、変更点を明確にするため。CVS や Subversion や VSS などの
バージョン管理ツールには、変更した箇所を表示する機能があるが、いずれも
行単位でしか変更点を表示できない。差分を知りたいときに

(変更前) "SELECT hoge, fuga, CASE WHEN moge=1 THEN 'a' moge=2 THEN 'b' ELSE 'c' END FROM table1 WHERE foo = ? AND bar = ? GROUP BY baz"
(変更後) "SELECT hoge, fuga, CASE WHEN moge=1 THEN 'a' moge=2 THEN 'b' ELSE 'd' END FROM table1 WHERE foo = ? AND bar = ? GROUP BY baz"

などと表示されたとしても、どこが変更されたのさっぱりわからない。複数行に分けて
書けば、どの行が変更されたのかが明確になる。
スポンサーサイト

PageTop

コメント


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