如何将变量连接成SQL字符串

cod*_*iac 5 sql sql-server-2008

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

ALTER FUNCTION fn_myfunction(@KeyValue text)
BEGIN
     INSERT INTO @tmpTbl1
     SELECT @KeyValue AS fld1
     FROM tbl + @KeyValue + KeyValue.fld1
Run Code Online (Sandbox Code Playgroud)

我也试过以下但它告诉我我必须声明表变量?

ALTER FUNCTION fn_myfunction(@KeyValue text, @KeyTable text)
     FROM @KeyTable.fld1
Run Code Online (Sandbox Code Playgroud)

spe*_*593 15

您可以使用动态SQL完成此操作(如果我了解您要执行的操作).

诀窍是你需要创建一个包含SQL语句的字符串.这是因为在执行语句时,必须在实际的SQL文本中指定tablename.表引用和列引用不能作为参数提供,它们必须出现在SQL文本中.

所以你可以使用这种方法:

SET @stmt = 'INSERT INTO @tmpTbl1 SELECT ' + @KeyValue 
    + ' AS fld1 FROM tbl' + @KeyValue

EXEC (@stmt)
Run Code Online (Sandbox Code Playgroud)

首先,我们将SQL语句创建为字符串.给定'FooValue'的'Foo',这将创建一个包含以下内容的字符串:

'INSERT INTO @tmpTbl1 SELECT Foo AS fld1 FROM tblFoo'
Run Code Online (Sandbox Code Playgroud)

此时,它只是一个字符串.但我们可以使用EXECUTE(或EXEC简称)作为动态SQL语句执行字符串的内容.

旧学sp_executesql过程是EXEC的替代方法,EXEC是另一种执行动态SQL的方法,它还允许您传递参数,而不是在语句的文本中将所有值指定为文字.


跟进

EBarr指出(正确而重要的是)这种方法容易受到SQL注入的影响.

考虑如果@KeyValue包含字符串会发生什么:

'1 AS foo; DROP TABLE students; -- '
Run Code Online (Sandbox Code Playgroud)

我们将作为SQL语句生成的字符串是:

'INSERT INTO @tmpTbl1 SELECT 1 AS foo; DROP TABLE students; -- AS fld1 ...'
Run Code Online (Sandbox Code Playgroud)

当我们将该字符串作为SQL语句执行时:

INSERT INTO @tmpTbl1 SELECT 1 AS foo;
DROP TABLE students;
-- AS fld1 FROM tbl1 AS foo; DROP ...
Run Code Online (Sandbox Code Playgroud)

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

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


Jan*_*ans 5

您可以这样使用Prepared Stements

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

prepare stmt from @like_q;
execute stmt;
Run Code Online (Sandbox Code Playgroud)

  • “@like_q”在这里意味着“@query”吗?您是否打算覆盖“@query”的值? (2认同)