本コーディング規約は、世の中のシステム開発プロジェクトのために無償で提供致します。
ただし、掲載内容および利用に際して発生した問題、それに伴う損害については、フューチャー株式会社は一切の責務を負わないものとします。
また、掲載している情報は予告なく変更することがございますので、あらかじめご了承下さい。
本書は、SQL コーディング規約についてまとめたものである。
今回 RDBMS として採用する PostgreSQL での SQL の使用を前提に記述している。
本章では可読性・管理性を高めることを目的としたコーディング規約について記載する。
書式全般についてのコーディング規約を下記に示す。
予約語に対しては、小文字を使用する。(例 : select
、insert
、update
、delete
等)
予約語以外に対しても、予約語と同様に小文字を使用する。(例 : オブジェクト名、カラム名 等)
SQL 中に記述するエイリアス名など単語の短縮について示す。
外来語に関しては、原語の短縮形を使用する。短縮形が存在しない場合には、母音を抜かして表記する。
例) corporation → corp / computer → cmptr
ローマ字の短縮は、単語の区切れの頭文字、または母音を抜かした子音字等を利用する。
例) nichijo → nchj
SQL ファイルの文字コード(エンコーディング)は Java ソースファイルと同じく『 Unicode UTF-8 』で保存する。
不要な空白文字(スペース)は除去すること。
DML 文の節に対する予約語は左揃えにする。
項目ごとに改行を入れ、項目の前にはインデントを挿入する。カンマは項目の前へ記入する。
Java ソースファイルのようにファイルの先頭にコメント行を入れると DB 分析作業に支障があるため禁止とする。
よって SQL ファイルの先頭は必ずselect
、update
、insert
、delete
の何れかになる。
物理カラム名、テーブル名に対応する論理名を入れる場合、その後ろに単数行コメント(--
)にて記述する。
SQL 内に挿入する単数行コメントは、/*(半角スペース)コメント本文(半角スペース)*/
で行う。
,
(カンマ)とAND
については各行の先頭に記述する。(以下の例を参照のこと)
SQL フレームワークで実行する SQL の場合、SQL ステートメントの終わりを示す;
(セミコロン)は記述しない。
良い例:
select
/*
処理名
*/
tbl1.column1 as column1 -- カラム1
, tbl1.column2 as column2 -- カラム2
from
table1 tbl1 -- テーブル1
WHERE 句の=
、!=
、is
(is null
のis
)の縦位置は揃える。
良い例:
良い例:
良い例:
良い例:
良い例:
良い例:
CASE 式は下記のように記載すること。
良い例:
case
、when
、then
、else
の後に改行を挿入すること。
case
の後、end
の前までは 1 インデント挿入すること。
カンマの後にスペースを1文字入れる。
比較演算子の前後にタブ(またはスペース)を1文字入れる。
select 句、order by 句、group by 句等は最初に出現するカラムとカラムの区切りのカンマ前に改行を入れること。
select の from 句の最初に出現するテーブルと結合テーブルの区切りのカンマ前に改行を入れること。
where 句の on 句の各条件文の(and や or の)前に改行を入れること。
命令句の後は、ヒント句が挿入できるように改行すること。
良い例:
with の前後に改行を挿入すること
また、インデントは下記のように記述すること
良い例:
LIMIT、OFFSET の前に改行を挿入すること
良い例:
HINT 句は独立した行で記載すること
HINT 内容にはインデントを付けること
良い例:
修正コメント
(修正コメントが必要な場合、)
処理追加の際、追加行の 1 行目の前と最終行の次の行にコメントを入れる。単一行の場合は、同一行の最後にコメントをつける。
良い例:
単数行コメント
SQL 内で使用する単数行コメント(カラムコメントなど)には、「 --
」を使用する。
複数行コメント
「 /*
*/
」を使用する。下記に例を示す。
なお、前述で触れたとおり、SQL ファイルの先頭にコメントを記述することは禁止とする。
良い例:
複数行コメントアウト
複数行をコメントアウトする場合は、各行を「--
」でコメントアウトする。
「 /*
*/
」を使用すると、その中に「 /*
*/
」が存在した場合、コメントアウトが途中で切れてしまう恐れがあるため、
使用しない。
論理名の記載
select
・insert
・update
・merge
のカラム名記述箇所には単数行コメントでカラムの論理名を記載する。
select
・insert
・update
・delete
・merge
のテーブル名記述箇所には単数行コメントでテーブルの論理名を記載する。
論理名は ERD 等で定義された論理名と必ず一致させること。
代入や WHERE 句の条件設定などでデータ・タイプが異なる場合、明示的にタイプ変換を行う。(暗黙の型変換は使用しない)
「等しくない」を示す演算子は「!=
」を利用する。「<>
」も動作するが統一の観点から利用しない。
order by
数字の構文は使用せずに、カラム名を記載する。
group by
数字の構文は使用せずに、カラム名を記載する。
集約関数を利用する場合は必ず記載すること。(省略可能であっても省略しない)
EXISTS 句を記載する際、サブクエリになる SELECT 句の指定は定数「1
」とする。
「*
」(ワイルドカード)や「'X'
」は統一の観点から利用しない。
また「*
」(ワイルドカード)についてはパフォーマンスの観点からも禁止とする。
良い例:
トップレベルの SELECT 句には必ずas
句を記載し別名を付ける。
同一の名前であっても AS 句を付与する。
また、「as
」は省略可能であるが、省略はしないこと。
論理名の記載
WHERE 句でカラムと式を比較する際は左辺がカラムになるように記載すること。
良い例:
条件式の順序
原則として、WHERE 句で条件式を列挙する際、下記の順序を守ること。
良い例:
from
a_table a -- a_table
, b_table b -- b_table
, c_table c -- c_table
where
-- a_tableの絞り込み
a.key1 = ?
and a.key2 = ?
-- b_tableの絞り込み
and b.key1 = ?
and b.key2 = ?
-- b_tableの結合条件
and b.col1 = a.col1
-- c_tableの絞り込み
and c.key1 = ?
and c.key2 = ?
-- c_tableの結合条件
and c.col1 = a.col1
and c.col2 = a.col2
and c.col3 = b.col3
レコード数を数える COUNT 文の記述はcount(*)
と記述する。
count(1)
・count('x')
・count(key1)
という記載は NG。
文字列リテラル中のシングルクォーテーションのエスケープは「 ''
」とシングルクォーテーションを二つつなげた記述をする。
「 \'
」も同様の結果が得られるが円マーク(バックスラッシュ)によるエスケープは利用しない。
円マークをエスケープせざるを得ないときのみ円マークによるエスケープ利用して良いが、
円マークを文字列リテラルで表現する必要のある設計自体を避けること。
※PostgreSQL は設定によって円マーク(バックスラッシュ)によるエスケープを無効にできます。(デフォルト無効)
円マークをエスケープするときは、自プロジェクトでどちらに設定されているか確認してください。
良い例:
悪い例:
本章ではパフォーマンス性を高めることを目的としたコーディング規約について記載する。
検索処理におけるコーディング規約を下記に示す。
中間一致、後方一致検索はインデックスを利用できないため避ける
検索条件で=
(等号)を使用できる場合は必ず使用する
a=1 or a=2
とする方がa>0 and a<3
などと記述するのよりパフォーマンス上優位な場合が多い。
これは a
にインデックスがある場合、=
であれば、インデックスが有効に使われるためである。
可能な限り検索条件にパーティションキーの値を指定する
全列ワイルドカード「*
」の使用はせず、カラム名を明記する
インデックスによる検索を指定したい場合、下記の記載を行わない
インデックスカラムを含む演算に対して条件指定
悪い例:
良い例:
インデックスカラムに関数を通した値に対して条件指定
悪い例:
良い例:
インデックスカラムをOR
で条件指定(禁止ではないが原則行わない)
悪い例:
挿入処理におけるコーディング規約を下記に示す。
*
」の使用はせず、カラム名を明記する。更新処理におけるコーディング規約を下記に示す。
削除処理におけるコーディング規約を下記に示す。
DISTINCT は、暗黙のソート処理が行われる可能性があるため性能劣化につながる。
EXISTS 句の使用・代替を検討すること。
悪い例:
select
distinct
d.no as dept_no
, d.name as dept_name
from
department d
, employee e
where
d.no = e.dept_no -- 社員が一人以上属している部門を取得
良い例:
IN 句は最大 1000 個まで指定できるが、200 個程度でも ORA エラーが発生するケースがある。
また IN 句の少しだけ異なる SQL が大量に発行されると CPU 高騰やメモリ枯渇を招く。
従って 100 を超えるような長い IN 句は使用せず、一時表を利用して in (select ・・・ from 一時表)
のように書き換える。
原則not in(select~)
は使用せずに、not exists (select~)
を使用する。
NOT IN
句は、内部的にソートマージの結合をすることでテーブルをフルスキャンする場合があるため、性能が悪化する可能性がある。
union
はdistinct
処理が含まれパフォーマンス上問題があるため、union all
を使用する。
select for update
で複数行にロックをかける場合、同時実行されるとデットロックを起こす可能性があるため、1件のロックでない場合はorder by
を指定する。分析関数の使用は可能だが、性能悪化を招く恐れがあるため、特性を知らない方は DBA に相談する。
インデックスの必要性については DBA で最終判断するため、必要とする場合は DBA へ相談する。
外部結合する際、内部表(駆動表)はなるべく想定件数の少ない表にする。