Можете да постигнете това (ако разбирам какво се опитвате да направите) с помощта на динамичен SQL.
Номерът е, че трябва да създадете низ, съдържащ SQL израза. Това е така, защото името на таблицата трябва да бъде указано в действителния SQL текст, когато изпълнявате оператора. Препратките към таблици и колони не могат да бъдат предоставени като параметри, те трябва да се показват в SQL текста.
Така че можете да използвате нещо като този подход:
SET @stmt = 'INSERT INTO @tmpTbl1 SELECT ' + @KeyValue
+ ' AS fld1 FROM tbl' + @KeyValue
EXEC (@stmt)
Първо създаваме SQL оператор като низ. Като се даде @KeyValue на 'Foo', това ще създаде низ, съдържащ:
'INSERT INTO @tmpTbl1 SELECT Foo AS fld1 FROM tblFoo'
В този момент това е просто низ. Но можем да изпълним съдържанието на низа като динамичен SQL израз, използвайки EXECUTE
(или EXEC
на кратко).
Старата школа sp_executesql
процедурата е алтернатива на EXEC, друг начин за изпълнение на dymamic SQL, който също ви позволява да предавате параметри, вместо да указвате всички стойности като литерали в текста на оператора.
ПОСЛЕДВАНЕ
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 ...
И не може да се инжектира само DROP TABLE. Всеки SQL може да бъде инжектиран и може да е много по-фин и дори по-престъпен. (Първите атаки могат да бъдат опити за извличане на информация за таблици и колони, последвани от опити за извличане на данни (имейл адреси, номера на сметки и др.)
Един от начините за справяне с тази уязвимост е да се потвърди съдържанието на @KeyValue, да се каже, че трябва да съдържа само букви и цифри (напр. проверете за знаци извън тези диапазони, като използвате LIKE '%[^A-Za-z0-9]%'
. Ако бъде открит незаконен знак, отхвърлете стойността и излезте, без да изпълнявате никакъв SQL.