如果我理解你想要做什么的话,你可以使用动态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'
此时,它只是一个字符串。但我们可以使用EXECUTE
(或简写为EXEC
)作为动态SQL语句来执行字符串的内容。
老派的sp_executesql
过程是EXEC的替代品,另一种执行动态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;
不只是DROP TABLE指令容易受到注入攻击,任何SQL指令都有可能遭到注入攻击,而且这种攻击可能更加微妙甚至更加恶意。第一轮攻击可能是为了获取关于表和列的信息,接着就会尝试检索数据(例如电子邮件地址、账号等)。
解决这个漏洞的一种方法是验证@KeyValue的内容,比如说它只应该包含字母和数字字符(例如使用LIKE '%[^A-Za-z0-9]%'
检查是否存在不在这些范围内的字符)。如果发现非法字符,则拒绝该值,并退出执行任何SQL指令。