SQLフォーマッター
SQLクエリを整形、または1行に圧縮
処理中…
0.0
停止していません。計算が終わると結果が表示されます。
SQLフォーマッターについて
このフォーマッターはSQLの構文を解析するパーサーではなく、文字列をトークン(キーワード・識別子・数値・文字列・コメント・記号)に分けて規則で改行する軽量ツールです。SELECT、FROM、WHERE、JOIN、GROUP BYなどの句ごとに改行し、既知のキーワードを大文字にし、SELECTのカンマやWHEREのAND/ORごとに行を分けます。単一引用符の文字列とコメントの中身は変えません。
パーサーではないので、クエリが正しいかは判断せず、データベースごとの方言もすべては知りません。以下ではMySQL・PostgreSQL・SQL Server固有の構文のうち何をそのまま保つか、また整形では解決しない問題を説明します。
方言の構文の扱い
標準SQLでは単一引用符が文字列、二重引用符が識別子で、文字列中の引用符は'It''s'のように2つ重ねます。このツールはこの規則とMySQLのバッククォート識別子`id`、そして以下の方言の構文を1つのまとまりとして扱います。
- MySQLのバックスラッシュエスケープ文字列('It\'s')は内容を変えずに残します。バックスラッシュとして読むと文字列が閉じない場合は、標準SQLの規則('')で読み直します。
- MySQLの#コメントを認識します。圧縮すると#コメントは消えるので、次の行がコメントに飲み込まれることはありません。PostgreSQLの#>、#>>、#-は演算子として扱います。
- PostgreSQLの->>、->、@>、<@、||、::は分割しません。::はcreated_at::dateのように前後に空白を入れません。$$ ... $$や$tag$ ... $tag$で囲んだ本体は文字列として扱い、変更しません。
- 文字列に接している記号は元の間隔を保ちます。array['a']はそのまま残ります。
- SQL Serverの角括弧識別子[order id]は空白を含めてそのまま残します。
- 圧縮では--と/* */のコメントを消しますが、/*+ ... */のオプティマイザヒントとMySQLの/*! ... */実行コメントは残します。
整形では直らないこと
代表的なのはANDとORの優先順位です。ANDのほうが先に結合するため、a = 1 OR b = 2 AND c = 3はa = 1 OR (b = 2 AND c = 3)です。フォーマッターはANDとORを同じ深さに並べるので、3つの条件が対等に見えてしまいます。意図が(a = 1 OR b = 2) AND c = 3なら括弧を自分で書く必要があります。
LEFT JOINの右側テーブルの条件をWHEREに書いた場合も同じです。注文のないユーザーではo.created_atがNULLになり、条件が真にならないため行が消え、結果はINNER JOINと同じになります。残したいなら条件をONに移します。= NULLが常にUNKNOWNになりIS NULLが必要な点も、整形前後ともに「有効なSQL」のままです。
例
1行のクエリを整える
- 入力
select u.id, u.name, count(o.id) as cnt from users u left join orders o on o.user_id = u.id where u.active = 1 and o.created_at >= '2026-01-01' group by u.id, u.name having count(o.id) > 3 order by cnt desc limit 10;- 結果
SELECT u.id, u.name, count(o.id) AS cnt FROM users u LEFT JOIN orders o ON o.user_id = u.id WHERE u.active = 1 AND o.created_at >= '2026-01-01' GROUP BY u.id, u.name HAVING count(o.id) > 3 ORDER BY cnt DESC LIMIT 10;
整形すると、WHEREのo.created_at条件がLEFT JOINを実質的に内部結合にしていることが見えてきます。countは関数名なので小文字のままです。
ANDとORが並んで見える
- 入力
select * from t where a = 1 or b = 2 and c = 3- 結果
SELECT * FROM t WHERE a = 1 OR b = 2 AND c = 3
実際の意味はa = 1 OR (b = 2 AND c = 3)です。
PostgreSQLの演算子を保つ
- 入力
select id, data->>'name' as n, created_at::date from t where tags @> array['a']- 結果
SELECT id, data ->>'name' AS n, created_at::date FROM t WHERE tags @> array['a']
->>、::、@>はそれぞれ1つのまとまりのまま残ります。文字列'name'に接している->>は元の間隔のままです。
圧縮時のヒントと#コメント
- 入力
SELECT /*+ INDEX(o idx_user) */ id FROM o # note WHERE a = 1- 結果
SELECT /*+ INDEX(o idx_user) */ id FROM o WHERE a = 1
オプティマイザヒントは残り、# noteのコメントだけが消えます。次の行のWHERE句はそのまま保たれます。
使い方
- SQLを貼り付けます。複数の文は;で区切ります。
- インデント幅を選び、整形または圧縮を押します。
- 結果を元のSQLと比べてから使います。
よくある質問
構文エラーを見つけてくれますか?
いいえ。トークン単位で改行するだけなので、誤ったクエリもそのまま整形されます。
関数名が小文字のままです。
大文字にするのは組み込みのキーワード一覧にある語だけです。
圧縮したSQLをコードに入れてもいいですか?
使えますが、通常のコメントは消え、ヒント(/*+ */)とMySQLの実行コメント(/*! */)だけが残ります。必要なコメントがないか確認してください。
PostgreSQLの演算子に対応していますか?
->>、->、@>、<@、||、::と$$のドル引用符は分割せずに残します。方言の設定はないので、それ以外の固有構文は元のSQLと比べてください。
出典
- MySQL 8.0 Reference Manual: Comments
- MySQL 8.0 Reference Manual: String Literals
- PostgreSQL: JSON Functions and Operators
- PostgreSQL: Operator Precedence
- Microsoft Learn: Database identifiers
基準日: