これは、動的SQLを使用して(私があなたがやろうとしていることを理解していれば)達成できます。
秘訣は、SQLステートメントを含む文字列を作成する必要があるということです。これは、ステートメントを実行するときに、テーブル名を実際のSQLテキストで指定する必要があるためです。テーブル参照と列参照をパラメータとして指定することはできません。これらはSQLテキストに表示する必要があります。
したがって、次のようなアプローチを使用できます。
SET @stmt = 'INSERT INTO @tmpTbl1 SELECT ' + @KeyValue
+ ' AS fld1 FROM tbl' + @KeyValue
EXEC (@stmt)
まず、SQLステートメントを文字列として作成します。 'Foo'の@KeyValueを指定すると、次を含む文字列が作成されます。
'INSERT INTO @tmpTbl1 SELECT Foo AS fld1 FROM tblFoo'
この時点では、それは単なる文字列です。ただし、EXECUTE
を使用して、動的SQLステートメントとして文字列の内容を実行できます。 (またはEXEC
略して)。
昔ながらのsp_executesql
プロシージャは、動的SQLを実行する別の方法であるEXECの代替手段であり、ステートメントのテキストですべての値をリテラルとして指定するのではなく、パラメータを渡すこともできます。
フォローアップ
EBarrは、このアプローチはSQLインジェクションの影響を受けやすいと(正しくそして重要に)指摘しています。
@KeyValue
の場合、どうなるか考えてみてください 文字列が含まれています:
'1 AS foo; DROP TABLE students; -- '
SQLステートメントとして生成する文字列は次のようになります。
'INSERT INTO @tmpTbl1 SELECT 1 AS foo; DROP TABLE students; -- AS fld1 ...'
その文字列をSQLステートメントとして実行する場合:
INSERT INTO @tmpTbl1 SELECT 1 AS foo;
DROP TABLE students;
-- AS fld1 FROM tbl1 AS foo; DROP ...
そして、注入できるのはDROPTABLEだけではありません。任意のSQLを挿入できますが、それははるかに微妙で、さらに悪質な場合があります。 (最初の攻撃は、テーブルと列に関する情報を取得しようとする試みであり、その後にデータ(電子メールアドレス、アカウント番号など)を取得しようとする試みが続きます。
この脆弱性に対処する1つの方法は、@ KeyValueの内容を検証することです。たとえば、アルファベットと数字のみを含める必要があります(たとえば、LIKE '%[^A-Za-z0-9]%'
。不正な文字が見つかった場合は、その値を拒否し、SQLを実行せずに終了します。