您可以使用动态 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
(or EXEC
简称)。
老派sp_executesql
procedure 是 EXEC 的替代方法,是执行动态 SQL 的另一种方法,它还允许您传递参数,而不是将所有值指定为语句文本中的文字。
FOLLOWUP
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。