歴史的に、可変数のグループ化を持つ動的レポートの課題はSQL標準では考慮されていませんでした — SQLは明確に定義された結果スキーマを持つ静的に記述されたクエリに基づいて設計されています。BIプラットフォームやインタラクティブダッシュボードの登場により、プログラマーはユーザーの要求に応じて複雑なデータのスライスを形成するために、「その場で」SQLクエリを構築する方法を模索しています。
問題 — SQLはSELECT内の通常のif/elseロジックでプログラムすることができません — 列数、フィールド自体、さらにはGROUP BYはクエリのコンパイル段階でのみ決定されます。ユーザーが複数の任意のフィールドでスライスを希望する場合、動的にクエリテキストを構築し、EXECUTE/Dynamic SQLを介して実行する必要があります。
解決策:
外部アプリケーションでSQLコードを生成し、次にEXEC/EXECUTEを介して呼び出します。場合によっては、簡単なタスクに対してCASEやハードコーディングテンプレートを使用しますが、柔軟性のために動的SQLが常に利用されます:
コードの例(擬似コード):
-- アプリケーション側(例:Python) groups = ['region', 'channel', 'month'] columns = [f'SUM({col}) AS {col}_sum' for col in selected_metrics] group_by = ', '.join(groups) selects = ', '.join(groups + columns) query = f'SELECT {selects} FROM sales GROUP BY {group_by}' -- 次に、このクエリをapplication/sqlインターフェースを介して送信
EXECUTEをサポートするDBMSでは:
DECLARE @sql NVARCHAR(MAX); SET @sql = N'SELECT ' + @selects + ' FROM sales GROUP BY ' + @group_by + ';'; EXEC sp_executesql @sql;
重要な特徴:
標準のSELECTだけで動的に列数を変更(ピボット/アンピボット)できますか?
いいえ — 事前に知られた値のみをCASE/DECODE経由で「展開」できますが、不明な列数は動的にしか達成できません。
文字列結合を使用している場合、動的SQLのロジックはインジェクションからの保護を保証しますか?
いいえ、手動の文字列結合はSQLインジェクションの常なるリスクです。フィールド/グループのリストをホワイトリストで検証し、事前確認なしにユーザーのフラグメントを避けることが必須で、可能であればパラメータを使用するのが望ましいです。
GROUP BYは変数を介して列のリストを受け取ることができますか?
標準SQLは、変数/パラメータを介してGROUP BYに列のリストを渡すことをサポートしていません。クエリテキストを動的に生成する必要があります — GROUP BYのリストに単に変数を使用することはできません。
BIエンジニアは、ユーザーがアプリケーションのインターフェースから直接レポートのフィールド名を渡すことを許可しました — それらをホワイトリストでフィルタリングしませんでした。その結果、インジェクションテストで、フィールド名に悪意のあるコードが埋め込まれて、プロダクションテーブルが「ダウン」しました。
長所:
短所:
エンジニアはフィールド名の厳格な検証を実装し、ユーザーは許可された列のみ(config/metadataから)を選択でき、動的SQLはホワイトリストのみに基づいて構築され、インジェクションのための経路は存在しませんでした。
長所:
短所: