クエリまたはスクリプトを貼り付けてください。各ステートメントはこのブラウザー内でテキストとして確認し、コメントと文字列リテラルはマスクするため、その中のキーワードを SQL と誤認しません。WITH の後ろでも文の種類を判定し、DELETE・UPDATE にはトップレベルの WHERE を要求し、リテラルとキャストの外にあるプレースホルダーを数えます。
ブラウザ内でローカルに実行貼り付けたスクリプトをステートメントに分割し、それぞれをテキストとして確認します。先頭のキーワードはトップレベルで読み取るため、WITH old AS (...) DELETE FROM users は SELECT ではなく DELETE として扱われます。実行計画への変換も、データベースへの送信も行いません。
確認するのはコードレビューで最初に見る項目です。文そのものに WHERE がない DELETE と UPDATE、DROP と TRUNCATE、SELECT * と行数上限のない SELECT、フィルター内のリテラル比較、トップレベルの 1=1 や OR TRUE、${...} のテンプレートプレースホルダー、文字列連結で組み立てた値です。
書き込みとして数えるのは INSERT、UPDATE、DELETE、MERGE、REPLACE、CREATE、ALTER、DROP、TRUNCATE です。文そのものに WHERE がない DELETE と UPDATE は危険の指摘になります。サブクエリ内の WHERE は外側の書き込みを保護しません。DROP と TRUNCATE は単独で危険の指摘、それ以外の書き込みは警告です。
SELECT では列リストのアスタリスク(t.* を含む)と行数上限を確認します。LIMIT、FETCH FIRST / NEXT ... ROWS ONLY、TOP n、ROWNUM <= n のいずれも上限として扱うため、上限なしの情報メモは無制限に行が返る可能性がある場合だけ表示されます。
プレースホルダーの数は、コメントと文字列リテラルの外にある ?・$1・:name・@name を対象にします。created_at::text のようなキャストや @@ROWCOUNT のような識別子は数えません。WHERE・AND・OR のフィルターでリテラルを比較している場合は、ドライバーのパラメーター構文を促す警告を出します。
文字列の組み立ては 2 種類を区別して報告します。${...} は値が文に展開されていることを意味し、リテラルと識別子の連結は文のテキストがドライバーの外で組み立てられていることを意味します。どちらもバインドパラメーターではなく、サーバーに届くテキストにとって重要な違いです。
分割処理は、引用符の二重化と MySQL のバックスラッシュエスケープ、二重引用符とバッククォートの識別子、-- と /* */ のコメント、行頭の # コメント、PostgreSQL の $$ で囲んだ本体、DELIMITER 指示を理解するため、エスケープされたアポストロフィや関数本体で文の数がずれません。複数文のスクリプトには警告が出て、各指摘にステートメント番号が付きます。
このページはデータベースに接続せず、何も実行せず、スキーマ・権限・行レベルセキュリティ・トランザクションも見えません。ここを通過した文が環境で破壊的になることはあります。クエリレビューの前のテキスト段階の確認として、EXPLAIN と周辺コードの確認と併用してください。