SQLが整形できない原因と方言の選び直し方
貼った SQL が整形できない、あるいは整形されたのに読めないときの切り分け手順です。方言によってプレースホルダの読める書き方が変わること、エラーにならずに素通りする入力があること、コメントの扱いで中身が減ることを、実測した件数で示します。
公開読了目安 約5分
この記事の要点
- 標準SQLが読めるプレースホルダは疑問符だけ
- 4つの書き方すべてを読める方言は14中2つ
- 整形が通ってもSQLとは限らない
- エラーにならない失敗の型が3つある
- コメントを消す設定は中身を実際に減らす
目次
SQL の整形がうまくいかないとき、原因は 2 つに分かれます。整形が止まる場合と、整形はされたのに読めない場合です。
前者は方言の選び方、後者は入力そのものの問題であることが多いです。この記事では、どちらなのかを切り分ける順番をまとめます。
操作そのものの手順はSQLを読める形に整形する手順にあります。ここでは整形が通らない側を扱います。
止まる原因のほとんどは方言の取り違え
SQL の整形ツールにはたいてい方言の選択肢があります。MySQL や PostgreSQL といった一覧です。
ここを外すと、ごく普通の SELECT 文でも止まります。よく起きるのがプレースホルダの書き方です。

上の画面は、方言を標準 SQL に固定したまま $1 を含む SQL を整形したものです。文としては何も間違っていません。
それでも止まります。標準 SQL が値の置き場所として認めているのが ? だけだからです。
4 つの書き方が、方言ごとにばらばらに通る
プレースホルダの書き方は主に 4 つあります。?、$1、:name、@name です。
どれが通るかを、SQL整形ツールが選択肢に持つ 14 の方言すべてで実際に試しました。結果が次の表です。
| 書き方 | 通った方言の数 | 通った方言 |
|---|---|---|
? | 14 中 9 | 標準SQL / PostgreSQL / MySQL / MariaDB / SQLite / BigQuery / DuckDB / Trino / Db2 |
$1 | 14 中 8 | PostgreSQL / MySQL / MariaDB / Redshift / Snowflake / DuckDB / Trino / Db2 |
:name | 14 中 8 | PostgreSQL / SQLite / SQL Server / Oracle / Snowflake / DuckDB / Trino / Db2 |
@name | 14 中 9 | PostgreSQL / MySQL / MariaDB / SQLite / SQL Server / BigQuery / Redshift / Oracle / Db2 |
4 つすべてを読めるのは PostgreSQL と Db2 の 2 つだけです。逆に標準 SQL は 4 つのうち 1 つしか読めません。
つまり「よく分からないから標準 SQL のまま」が、いちばん止まりやすい選び方になります。
迷ったら方言を固定しない
同ツールの方言は既定が「自動で探す」です。標準 SQL から順に試し、読めた方言を使います。

さきほど止まった SQL も、そのままなら PostgreSQL で通ります。どれで読めたかは結果の上に名前で出ます。
方言を固定するのは、出力の細かい違いまで合わせたいときだけで十分です。
整形が通ったのに読めないときの 3 つの型
止まらなかったのに結果がおかしい、という場合もあります。ここからは入力側の問題です。
型 1: そもそも SQL として読まれていない
意外に思われますが、SQL でない文字列を貼ってもエラーになりません。そのまま返ってきます。

select from where のような文字列も止まりません。3 行に並び替えられて返ってきます。
ここから言えるのは、整形が通ったことは SQL が正しいことの証明ではないという 1 点です。構文の確認には使えません。
同ツールは予約語が 1 つも見つからないときに断りを出します。ただしこれも予約語の有無を見ているだけで、正しさの判定ではありません。
型 2: コメントが消えている
多くの整形ツールに「コメントを削除する」という設定があります。これを入れたまま使うと、-- や /* */ の中身が消えます。
消えたこと自体は設定どおりです。困るのは、何件消えたかが分からないまま結果をコピーしてしまうことです。
同ツールは既定でコメントを残します。消す設定にしたときだけ「コメントを 2 件取り除きました」と件数を出します。
型 3: 文が 1 つだと思っていたら複数あった
ログからコピーすると、; をまたいで 2 文以上が混ざることがあります。1 文のつもりで読み進めて、途中から別のクエリだった、という取り違えが起きます。
同ツールは ; で区切って数え、2 文以上なら「2 文が含まれています」と出します。文字列やコメントの中の ; は数えません。
値が読めないのは整形の問題ではない
「整形したのに中身が分からない」という詰まり方もあります。これは書式ではなく、値がその場に無いことが原因です。
ORM やフレームワークが出すログは、SQL と値を別の行に書きます。WHERE created_at BETWEEN ? AND ? だけ見ても、いつのデータかは分かりません。
この場合に必要なのは整形ではなく、値を当てる操作です。同ツールでは「値を当てる」を開いてログの値を貼ると、? の位置に入ります。
なお、値を埋めた SQL はログを読むための形です。プレースホルダは値を連結しないための仕組みなので、埋めた形をそのまま実行する用途には向きません。
切り分けの順番
ここまでをまとめると、次の順で見るのが早いです。
- 整形が止まったか、通ったかを見る
- 止まったなら、まず方言を「自動で探す」に戻す
- それでも止まるなら、読めた方言の一覧が出ているかを見る。1 つも出なければ括弧と引用符の閉じ忘れを疑う
- 通ったのに読めないなら、予約語の断り・コメントの件数・文の件数を順に見る
- 値が分からないだけなら、整形ではなく値を当てる
止まったときに出る行と桁は、整形前の SQL での位置です。整形後の行番号ではないので、手元のエディタでそのまま探せます。
ただし値を当てた場合は別です。値の長さだけ桁が動くので、画面に出る行と桁は値を入れたあとの SQLでの位置になります。そのときは断りが一緒に出ます。
関連するツール
SQL を文字列としてソースへ埋め込むなら、文字列エスケープが続きを引き受けます。1 行にまとめた結果をそのまま渡せます。
設定ファイルの側で同じように行と桁の案内が要るなら、YAML⇔JSON変換とJSON整形ツールが同じ形でエラーを出します。
あわせて読みたい
同じテーマ・関連ツールの記事です。