(2)1行が長くなりやすい 演算の優先順位に注意 |
SQL文の1行は,C/C++などの汎用プログラミング言語に比べて長くなりやすい。SQL文は処理手続きを記述せず,1行にひとかたまりの処理内容を記述する。そのため複雑な条件を指定することになるからだ。1行が長いと,SQL文が読みにくくなるだけでなく,演算の優先順位にまつわるミスを起こしやすい。
迷ったときはカッコをつける
SQLの算術演算,論理演算の優先順位は,汎用のプログラミング言語と基本的に同じである。足し算や引き算よりも,掛け算や割り算の方が優先順位が高い。また,SQL文では論理演算をよく使うが,その優先順位は高い方から,NOT,AND,ORの順になる(図4[拡大表示])。
算術演算と論理演算の優先順位による,間違ったSQL文の例を示そう。(図5[拡大表示])(1)は,算術演算の優先順位を間違えた例である。「年収が300万円以上の社員」を検索するのに,間違えて,
SELECT SYAIN_NO, SYAIN_MEI
FROM SYAIN_TBL
WHERE KIHON + TEATE * 12 > 3000000 ;
としてしまった。計算したいことは,毎月の基本給(KIHON)と手当て(TEATE)の合計に,12を掛けて年収とし,300万円よりも多いかどうかを判定すること。しかしこのSQL文は正しくない。足し算よりも掛け算の方が優先順位が高いため,「KIHON + (TEATE X 12)」(基本給1カ月分と手当て12カ月分)を計算したことになる。正しいSQL文のWHERE句は,WHERE (KIHON + TEATE) * 12 > 3000000
である。このようなミスは汎用プログラミング言語でも起こり得るが,1行が長くなりがちなSQLでは見落としやすい。図5(2)は,論理演算の優先順位を間違えた例である。「基本給が20万円台ではなく,手当てを5万円以上もらっている社員」を検索するのに,
SELECT SYAIN_NO, SYAIN_MEI
FROM SYAIN_TBL
WHERE KIHON < 200000 OR
KIHON >= 300000 AND
TEATE >= 50000 ;
としてしまった。ORとANDでは,ANDの方が優先されるため,「KIHON < 200000 OR (KIHON >= 300000 AND TEATE >= 50000)」((1)基本給が20万円以上,または,(2)基本給が30万円以上かつ手当てが5万円以上)を計算したことになる。正しいSQL文のWHERE句は,WHERE (KIHON < 200000 OR
KIHON >= 300000) AND
TEATE >= 50000
としなければならない。迷った場合は,カッコを付けよう。句ごとの改行,字下げ,コメントで読みやすく
このようなミスを防ぐためには,1行が長くなりがちなSQL文を,できるだけ読みやすくしておくことが大切である。実際のアプリケーション開発においても,複雑なSQL文であるほど,メンテナンス時に何をやっているSQL文なのかを思い出すのに時間が掛かるといったことがよくある。第三者が見ても分かりやすいSQL文を書くように心掛けたい。
SQL文を読みやすくする基本は,改行や字下げ,コメントを適切に使うことである(図6[拡大表示])。
まず,SQL文はFROM句やWHERE句などの複数の句から成り立つので,各句ごとに改行する。
SELECT BUMON_MEI FROM BUMON_TBL
と書くのではなく,SELECT BUMON_MEI
FROM BUMON_TBL
と書く。また,条件を記述するWHERE句などは長くなりやすいので,その場合は,適当に改行して字下げを行う。WHERE (KIHON < 200000 OR KIHON >= 300000) AND TEATE >= 50000
では読みにくいので,WHERE (KIHON < 200000 OR
KIHON >= 300000) AND
TEATE >= 50000
とする。テーブルの別名を利用すれば,SQL文の長さを短くすることができる。具体的には,
SELECT BUMON_MEI,SYAIN_MEI
FROM SYAIN_TBL S,BUMON_TBL B
WHERE S.BUMON_CD = 10
AND S.BUMON_CD = B.BUMON_CD ;
における,「S」と「B」が別名だ。「S」は実際は「SYAIN_TBL」のことであり,「B」は「BUMON_TBL」のことである。SQL文にはコメントをつけることが可能である。SQL文の中に,処理の概要や目的,用途などを日本語で記述できる。SQL文のコメントは,「/*」と「*/」で囲むか,「--」を使う。「--」の場合は,行末までをコメントとみなす。
オブジェクト名の日本語使用は控える
日本語を使用するとSQL文は読みやすくなるが,テーブル名などに日本語を使用するのはできるだけ避けたい。
Oracleに限らず,主要なRDBMSでは,テーブル名などのオブジェクト名に日本語などのマルチバイト・コードが利用できる。分かりやすさの観点からは日本語の利用は優れているが,OSや利用するツールなどでマルチバイト・コードが使えない場合が考えられるため,利用は控えたい。例えばデータベースの障害が発生して復旧する場合,サーバーOSにログインしてRDBMSにアクセスし,エクスポートやインポートを行おうとしても,そのOSでマルチバイト・コードが使えなければデータベース・オブジェクトを指定することができない。また,データベースからのメッセージ出力などもマルチバイト・コードでは化けてしまうことが考えられる。
どうしても日本語名を使いたければ,シノニム*やビュー*を使えばよい。テーブルなどは英数字で定義し,その別名としてシノニムを定義してシノニムに日本語名をつける。そうすれば,英数字の名前でも,日本語の名前でもアクセスできるようになる。
(3)検索結果の順番にまつわるミス 指定しない限り,順番は不定 |
RDBMSのレコードの順番には注意が必要だ。テスト環境などでわずか数行のテーブルしかない場合,検索結果のレコードの順番は毎回同じになるだろう。しかし実際は,SELECT文の検索結果のレコードの順番は,指定しない限り不定である(図7[拡大表示])。例えば,
SELECT BUMON_CD, BUMON_MEI
FROM BUMON_TBL ;
というSQL文の結果は,たまたまBUMON_CD BUMON_MEI
10 AAA
20 BBB
30 CCC
になるかもしれないが,30 CCC
10 AAA
20 BBB
になることだってあり得る。BUMON_CDの順番で必ず出力させたい場合は,SELECT BUMON_CD, BUMON_MEI
FROM BUMON_TBL
ORDER BY BUMON_CD ;
とし,ORDER BY*句をつける。ただし,意味も無いのに並び順を指定してはいけない。レコードの並べ替えは負荷の高い処理なので,必要な場合にのみ指定する。
ソートにおいて注意したいのは,文字列カラムをソート・カラムに指定した場合だ(図8[拡大表示])。例えば,
SELECT SYAIN_MEI, ADDR
FROM SYAIN_TBL
ORDER BY ADDR ;
とした場合,住所の順番で結果を出力するが,その際の順番は文字コードの順番となるので気を付けたい。また,文字列の中に数字が混じっている場合,直観的な順番と異なる順になることがある。先ほどの例では,
えええ XXX10丁目
あああ XXX1丁目
いいい XXX2丁目
ううう XXX3丁目
おおお XXX4丁目
と出力される。しかし人が見た場合,あああ XXX1丁目
いいい XXX2丁目
ううう XXX3丁目
おおお XXX4丁目
えええ XXX10丁目
と並んだ方がきれいである。このような場合,ストアド・ファンクション*を作るなどの方法で,ある程度回避することができる。住所の「丁目」の前まで読み,ソートし,その後の丁目の数字文字列の部分を数値に変換してソートする。実際には住所は結構複雑なので簡単ではないが,ある程度見やすい並びにすることができる。
◇ ◇ ◇次回は文字列やSQLの関数に焦点をあてて,注意点を解説する予定である。
玉川 敏一(たまがわ としいち) シーズ・ラボ ITソリューション部 セクションマネージャー 1980年代後半からリレーショナル・データベースを利用している。当初は汎用機上のRDBMSであったが,1994年(株)シーズ・ラボ入社以来,Oracle一筋になる。同社にてシステム開発,研修インストラクタ,サポート窓口,技術支援業務を行い,Oracleと深くかかわっている。Oracle Master Platinum資格を保有。 |