SQL 整形ルール:可読性を上げるインデントと改行のスタイル
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 フォーマッターが使えます。