SQL 整形ルール:可読性を上げるインデントと改行のスタイル

約4分

SQL は改行とインデントの自由度が高く、書き方次第で可読性が大きく変わります。本記事では一般的なフォーマットスタイルとルールを整理します。

整形しないとどうなるか

SELECT u.id, u.name, COUNT(o.id) AS order_count FROM users u LEFT JOIN orders o ON o.user_id = u.id WHERE u.active = TRUE AND u.created_at > '2024-01-01' GROUP BY u.id, u.name HAVING COUNT(o.id) > 0 ORDER BY order_count DESC;

1 行に詰まっていると読みづらく、レビューや修正でミスが増えます。

縦並びキーワード形式(一般的)

主要キーワードを左揃え、列やテーブルをインデント:

SELECT
    u.id,
    u.name,
    COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE u.active = TRUE
  AND u.created_at > '2024-01-01'
GROUP BY u.id, u.name
HAVING COUNT(o.id) > 0
ORDER BY order_count DESC;

特徴:

  • 各句(SELECT, FROM, WHERE 等)が一目でわかる
  • 列の追加・削除が容易(diff も読みやすい)
  • AND / OR の継続行をインデント

ANSI 形式(右揃え)

キーワードを右揃え、要素を SELECT の右隣から始める:

  SELECT u.id,
         u.name,
         COUNT(o.id) AS order_count
    FROM users u
    LEFT JOIN orders o ON o.user_id = u.id
   WHERE u.active = TRUE
     AND u.created_at > '2024-01-01'
GROUP BY u.id, u.name
  HAVING COUNT(o.id) > 0
ORDER BY order_count DESC;

特徴:

  • 列がきれいに揃う
  • 入力が手間(スペース調整が大変)
  • 列名の長さが変わると再整形が必要

最近は左揃えが主流。

句別の整形ルール

SELECT 句

カラムごとに改行:

SELECT
    u.id,
    u.name,
    u.email
FROM users u

カンマを行頭か行末か、好みが分かれる:

-- 行頭カンマ
SELECT
    u.id
  , u.name
  , u.email

-- 行末カンマ(一般的)
SELECT
    u.id,
    u.name,
    u.email

行頭カンマは「行を消す/入れ替える時にカンマミスが少ない」、行末カンマは「自然な英文の書き方」。

JOIN 句

各 JOIN を独立した行に:

FROM users u
LEFT JOIN orders o ON o.user_id = u.id
LEFT JOIN products p ON p.id = o.product_id

ON 条件が複雑な場合:

LEFT JOIN orders o
    ON o.user_id = u.id
   AND o.deleted_at IS NULL

WHERE 句

AND / OR を行頭に:

WHERE u.active = TRUE
  AND u.created_at > '2024-01-01'
  AND u.role IN ('admin', 'editor')

OR を含む場合は括弧で明示:

WHERE u.active = TRUE
  AND (
       u.role = 'admin'
    OR u.role = 'editor'
  )

優先順位は AND が OR より高いため、混在時は括弧推奨。

大文字小文字

キーワードは慣習的に大文字:

SELECT * FROM users WHERE id = 1;

最近は小文字で統一する流派も:

select * from users where id = 1;

統一されていれば良い。チームで決めるべき項目。

識別子の引用

PostgreSQL / SQL 標準ではダブルクォート:

SELECT "user_id" FROM "users";

MySQL ではバッククォート:

SELECT `user_id` FROM `users`;

予約語をテーブル名・列名にしない限り、引用は不要。

サブクエリ

ネストはインデントを増やす:

SELECT u.name
FROM users u
WHERE u.id IN (
    SELECT user_id
    FROM orders
    WHERE total > 1000
);

CTE(共通テーブル式)を使うと読みやすい:

WITH high_spenders AS (
    SELECT user_id
    FROM orders
    WHERE total > 1000
)
SELECT u.name
FROM users u
JOIN high_spenders h ON h.user_id = u.id;

関数の呼び出し

引数が長い場合は改行:

SELECT
    COALESCE(
        u.preferred_name,
        u.full_name,
        'Unknown'
    ) AS display_name
FROM users u;

短いものは 1 行:

SELECT COALESCE(u.name, 'Anon') FROM users u;

CASE 式

WHEN を縦並び:

SELECT
    CASE
        WHEN u.age < 18 THEN 'minor'
        WHEN u.age < 65 THEN 'adult'
        ELSE 'senior'
    END AS age_group
FROM users u;

インデントの幅

  • 4 スペース:見やすいが横に広がる
  • 2 スペース:詰めて書ける、深いネストで便利
  • タブ:環境依存、避けるのが安全

ツール(dbt、SQLFluff など)でフォーマット規約を統一するのが現実的。

コメント

行コメントとブロックコメント:

-- 単一行コメント

/*
 * 複数行コメント
 * 用途・意図を書く
 */

SELECT u.name
FROM users u
WHERE u.active = TRUE  -- 削除済みは除外
  AND u.created_at > '2024-01-01';  -- 新規ユーザのみ

「なぜそうしているか」を残すのが良い。

数値と文字列の引用

  • 文字列はシングルクォート'hello'
  • 数値はそのまま42
  • NULL はキーワードNULL(クォートしない)

'NULL' は文字列の “NULL” であり、SQL の NULL ではない。よくあるバグ。

自動整形ツール

手で整形するより自動化が現実的:

  • SQLFluff — Python 製のリンター・フォーマッター
  • pgFormatter — PostgreSQL 用
  • sql-formatter — JavaScript 製
  • Prettier (sql-formatter プラグイン) — Prettier に統合
  • dbt — モデルファイル向けに dbt format

CI で自動チェック・整形すれば、PR の差分がノイズだけにならずに済む。

まとめ

  • 縦並びキーワード形式(左揃え)が現代の主流
  • 句ごとに改行、AND / OR を行頭に
  • カンマは行末が一般的(行頭派もいる)
  • CTE はサブクエリより読みやすい
  • 自動整形ツールでチームの規約を統一

SQL を整形したいときは、本サイトの SQL フォーマッターが使えます。