14

我需要将变量表名连接到我的 SQL 查询中,例如以下...

ALTER FUNCTION fn_myfunction(@KeyValue text)
BEGIN
     INSERT INTO @tmpTbl1
     SELECT @KeyValue AS fld1
     FROM tbl + @KeyValue + KeyValue.fld1

我还尝试了以下操作,但它告诉我必须声明表变量?

ALTER FUNCTION fn_myfunction(@KeyValue text, @KeyTable text)
     FROM @KeyTable.fld1
4

2 回答 2

22

您可以使用动态 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但是我们可以使用(或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;
-- AS fld1 FROM tbl1 AS foo; DROP ...

而且它不仅仅是可以注入的 DROP TABLE。任何 SQL 都可以被注入,而且它可能更加微妙甚至更加邪恶。(第一次攻击可能是尝试检索有关表和列的信息,然后尝试检索数据(电子邮件地址、帐号等)

解决此漏洞的一种方法是验证 @KeyValue 的内容,说它应该只包含字母和数字字符(例如,使用 . 检查不在这些范围内的任何字符LIKE '%[^A-Za-z0-9]%'。如果发现非法字符,则拒绝该值并退出不执行任何 SQL。

于 2013-07-19T19:46:14.240 回答
6

你可以Prepared Stements这样使用。

set @query = concat( "select name from " );
set @query = concat( "table_name"," [where condition] " );

prepare stmt from @like_q;
execute stmt;
于 2013-07-19T19:48:12.963 回答