SQLコーディング規約(PostgreSQL)

Future Enterprise Coding Standards

本コーディング規約は、世の中のシステム開発プロジェクトのために無償で提供致します。
ただし、掲載内容および利用に際して発生した問題、それに伴う損害については、フューチャー株式会社は一切の責務を負わないものとします。
また、掲載している情報は予告なく変更することがございますので、あらかじめご了承下さい。

1 はじめに

1.1 前提条件

本書は、SQL コーディング規約についてまとめたものである。
今回 RDBMS として採用する PostgreSQL での SQL の使用を前提に記述している。

2 SQL コーティング規約(可読性・管理性)

本章では可読性・管理性を高めることを目的としたコーディング規約について記載する。

2.1 書式全般

書式全般についてのコーディング規約を下記に示す。

2.2 予約語

予約語に対しては、小文字を使用する。(例 : selectinsertupdatedelete 等)

2.3 予約語以外

予約語以外に対しても、予約語と同様に小文字を使用する。(例 : オブジェクト名、カラム名 等)

2.4 短縮名称

SQL 中に記述するエイリアス名など単語の短縮について示す。

  1. 外来語に関しては、原語の短縮形を使用する。短縮形が存在しない場合には、母音を抜かして表記する。
    例) corporation → corp / computer → cmptr

  2. ローマ字の短縮は、単語の区切れの頭文字、または母音を抜かした子音字等を利用する。
    例) nichijo → nchj

2.5 文字コード

SQL ファイルの文字コード(エンコーディング)は Java ソースファイルと同じく『 Unicode UTF-8 』で保存する。

2.6 不要な空白文字(スペース)は除去する

不要な空白文字(スペース)は除去すること。

2.7 SQL 文の整形

DML 文の節に対する予約語は左揃えにする。
項目ごとに改行を入れ、項目の前にはインデントを挿入する。カンマは項目の前へ記入する。
Java ソースファイルのようにファイルの先頭にコメント行を入れると DB 分析作業に支障があるため禁止とする。
よって SQL ファイルの先頭は必ずselectupdateinsertdeleteの何れかになる。

物理カラム名、テーブル名に対応する論理名を入れる場合、その後ろに単数行コメント(--)にて記述する。
SQL 内に挿入する単数行コメントは、/*(半角スペース)コメント本文(半角スペース)*/ で行う。
,(カンマ)とANDについては各行の先頭に記述する。(以下の例を参照のこと)
SQL フレームワークで実行する SQL の場合、SQL ステートメントの終わりを示す;(セミコロン)は記述しない。

良い例:

select
/*
    処理名
*/
    tbl1.column1    as  column1 -- カラム1
,   tbl1.column2    as  column2 -- カラム2
from
    table1  tbl1    -- テーブル1

WHERE 句の=!=isis nullis)の縦位置は揃える。

良い例:

where
    a.ten_no    =   b.ten_no
and a.kamoku_cd !=  '1'
and a.anken_no  is  null

2.7.1 SELECT 文

良い例:

select
    tbl1.column1    as  column1 -- カラム1
,   tbl1.column2    as  column2 -- カラム2
from
    table1  tbl1    -- テーブル1
where
    tbl1.column3    =   1
order by
    tbl1.column1
,   tbl1.column2

2.7.2 INSERT 文

良い例:

insert
into
    table1  -- テーブル1
(
    column1 -- カラム1
,   column2 -- カラム2
,   column3 -- カラム3
) values (
    value1
,   value2
,   value3
)

2.7.3 UPDATE 文

良い例:

update
    table1  tbl1    -- テーブル1
set
    tbl1.column2    =   100 -- カラム2
,   tbl1.column3    =   100 -- カラム3
where
    tbl1.column1    =   10

2.7.4 DELETE 文

良い例:

delete
from
    table1  tbl1    -- テーブル1
where
    tbl1.value  =   1

2.7.5 AND(副問い合わせ)

良い例:

and xxx =   (
        select
            tbl1.column1
        ,   tbl1.column2
        from
            table1  tbl1
    )

2.7.6 CASE 式

CASE 式は下記のように記載すること。

良い例:

case
    when
        xxx.hoge    =   yyy.fuga
    and xxx.fuga    =   yyy.fuga
    then
        1
    else
        0
end

casewhenthenelseの後に改行を挿入すること。
caseの後、endの前までは 1 インデント挿入すること。

2.7.7 IN 句

カンマの後にスペースを1文字入れる。

2.7.8 比較演算子

比較演算子の前後にタブ(またはスペース)を1文字入れる。

2.7.9 改行位置

select 句、order by 句、group by 句等は最初に出現するカラムとカラムの区切りのカンマ前に改行を入れること。
select の from 句の最初に出現するテーブルと結合テーブルの区切りのカンマ前に改行を入れること。
where 句の on 句の各条件文の(and や or の)前に改行を入れること。
命令句の後は、ヒント句が挿入できるように改行すること。

良い例:

select
    t1.column1  as  column1
,   t2.column2  as  column2
from
    table1  t1
,   table2  t2
where
    t1.column3  =   1
and t1.column4  =   t2.column4
order by
    t1.column1
,   t2.column2

2.7.10 WITH 句

with の前後に改行を挿入すること
また、インデントは下記のように記述すること

良い例:

-- カラムエイリアスあり
with
    name1   (
        col_alias1  -- カラム1
    ,   col_alias2  -- カラム2
    )   as  (
        select
        ・・・
    )
,   name2   (
        col_alias1  -- カラム1
    ,   col_alias2  -- カラム2
    )   as  (
        select
        ・・・
    )

-- カラムエイリアスなし
with
    name1   as  (
        select
        ・・・
    )
,   name2   as  (
        select
        ・・・
    )

2.7.11 LIMIT 句 OFFSET 句

LIMIT、OFFSET の前に改行を挿入すること

良い例:

select
    tbl1.column1    as  column1
from
    table1  tbl1
order by
    tbl1.column2    desc
limit 5
offset 5

2.7.12 HINT 句

HINT 句は独立した行で記載すること
HINT 内容にはインデントを付けること

良い例:

select
/*+
    ここにhintを記載
*/
    tbl1.column1    as  column1
from
    table1  tbl1
where
    tbl1.column2    =   1

2.8 コメント

2.9 型変換

代入や WHERE 句の条件設定などでデータ・タイプが異なる場合、明示的にタイプ変換を行う。(暗黙の型変換は使用しない)

2.10 比較演算子

「等しくない」を示す演算子は「!=」を利用する。「<>」も動作するが統一の観点から利用しない。

2.11 ORDER BY 句

order by 数字の構文は使用せずに、カラム名を記載する。

2.12 GROUP BY 句

group by 数字の構文は使用せずに、カラム名を記載する。

集約関数を利用する場合は必ず記載すること。(省略可能であっても省略しない)

2.13 EXISTS 句

EXISTS 句を記載する際、サブクエリになる SELECT 句の指定は定数「1」とする。
*」(ワイルドカード)や「'X'」は統一の観点から利用しない。
また「*」(ワイルドカード)についてはパフォーマンスの観点からも禁止とする。

良い例:

where
    exists(
        select
            1
        from
            foo f
        where
            f.col1  =   m.key
    )

2.14 AS 句

トップレベルの SELECT 句には必ずas句を記載し別名を付ける。
同一の名前であっても AS 句を付与する。
また、「as」は省略可能であるが、省略はしないこと。

2.15 WHERE 句

2.16 COUNT 文

レコード数を数える COUNT 文の記述はcount(*)と記述する。
count(1)count('x')count(key1)という記載は NG。

2.17 文字列リテラル

2.17.1 エスケープシーケンス

文字列リテラル中のシングルクォーテーションのエスケープは「 '' 」とシングルクォーテーションを二つつなげた記述をする。
\' 」も同様の結果が得られるが円マーク(バックスラッシュ)によるエスケープは利用しない。
円マークをエスケープせざるを得ないときのみ円マークによるエスケープ利用して良いが、
円マークを文字列リテラルで表現する必要のある設計自体を避けること。

※PostgreSQL は設定によって円マーク(バックスラッシュ)によるエスケープを無効にできます。(デフォルト無効)
円マークをエスケープするときは、自プロジェクトでどちらに設定されているか確認してください。

良い例:

update
    table_a
set
    text_data   =   'that''s right'

悪い例:

update
    table_a
set
    text_data   =   'that\'s too bad'

3 SQL コーディング規約(パフォーマンス性)

本章ではパフォーマンス性を高めることを目的としたコーディング規約について記載する。

3.1 検索

検索処理におけるコーディング規約を下記に示す。

3.2 挿入

挿入処理におけるコーディング規約を下記に示す。

3.3 更新

更新処理におけるコーディング規約を下記に示す。

3.4 削除

削除処理におけるコーディング規約を下記に示す。

3.5 DISTINCT 句

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   -- 社員が一人以上属している部門を取得

良い例:

select
    d.no    as  dept_no
,   d.name  as  dept_name
from
    department  d
where
    exists(
        select
            1
        from
            employee    e
        where
            d.no    =   e.dept_no   -- 社員が一人以上属している部門を取得
    )

3.6 IN 句

IN 句は最大 1000 個まで指定できるが、200 個程度でも ORA エラーが発生するケースがある。
また IN 句の少しだけ異なる SQL が大量に発行されると CPU 高騰やメモリ枯渇を招く。
従って 100 を超えるような長い IN 句は使用せず、一時表を利用して in (select ・・・ from 一時表)のように書き換える。

3.7 NOT IN 句

原則not in(select~)は使用せずに、not exists (select~)を使用する。
NOT IN句は、内部的にソートマージの結合をすることでテーブルをフルスキャンする場合があるため、性能が悪化する可能性がある。

3.8 UNION 句

uniondistinct処理が含まれパフォーマンス上問題があるため、union allを使用する。

3.9 SELECT FOR UPDATE

3.10 分析関数

分析関数の使用は可能だが、性能悪化を招く恐れがあるため、特性を知らない方は DBA に相談する。

3.11 インデックス

インデックスの必要性については DBA で最終判断するため、必要とする場合は DBA へ相談する。

3.12 外部結合

外部結合する際、内部表(駆動表)はなるべく想定件数の少ない表にする。


4 License

CC-By-4.0