SQL变量作为Where子句中的列名

时间:2013-08-21 14:25:03

标签: sql sql-server tsql

我需要一些SQL逻辑方面的帮助,而且我已经工作(并研究)了2天,但没有成功。

我的目标是尝试将ASP页面中的变量传递给存储过程,该存储过程将该变量用作where子句中列名的条件。

例如(我的查询的简化版):

@strDept nvarchar(10), @strUser nvarchar(30)
-- The asp page will pass f18 to @strDept & Ted Lee to strUser
-- f18 is the column name in my database that I need in the where.

select x, y, z from table1 where @strDept in (@strUser)
-- and this is the select statement, notice the where clause.

存储过程确实执行,但它不返回任何值,我知道它将@strDept视为文字nvarchar而不是列名。

所以我想我的问题是,如何让SQL Server 2005将@sqlDept变量视为列名?

7 个答案:

答案 0 :(得分:7)

您无法找到如何执行此操作的指导原因是非常糟糕

迟早,有人会传递1 ;drop database badidea的“列名”。这将是所有有关方面的祝福。

阅读SQL注入,重新考虑您的设计。

答案 1 :(得分:5)

如果这是一个内部公司应用程序,为什么每个人都重新迭代并击败SQL注入死...只是使用动态SQL非常简单。 如果您觉得这些只是内部用户使用它,那么它非常简单。这是概念。您基本上编写了一个SQL语句,该语句编写的字符串实际上是一个SQL语句,然后执行它。

CREATE Procedure myDynamicProcedure
@strDept nvarchar(10), 
@strUser nvarchar(30)

as 

BEGIN

<强> 1。声明一个变量来存储SQL语句。

 DECLARE @SQL varchar(max)

<强> 2。将您的@SQL变量设置为SELECT语句。基本上你正在构建它,所以它返回你想要写的东西。像这样:

   SET @SQL = 'select x, y, z from table1 where' + @strDept + 
 ' in ' + @strUser

第3。执行@SQL语句,它就像你运行的那样: 从table1中选择x,y,z,其中f18 ='Ted Lee'

EXEC (@SQL)
END

答案 2 :(得分:3)

为什么要使列名称动态化?你打算做什么?您可以像上面的回答一样使用动态查询,但可能会开始注入攻击。

如果你解释你想做什么,也许我们可以推荐另一种解决方案。

答案 3 :(得分:1)

你可以使用一些动态的sql,例如

DECLARE @sqlDept VARCHAR(100)='CURRENT_TIMESTAMP';

EXEC('SELECT '+@sqlDept)

在你的情况下,这将是

DECLARE @strDept nvarchar(10)='dept1'
,@strUser nvarchar(30)='user1';

DECLARE @DynamicSql nvarchar(1000);

SET @DynamicSql='select x, y, z from table where '+@strDept+' in ('''+@strUser+''')';

然后

SELECT @DynamicSql;

会给你:

  

从表格中选择x,y,z(&#39; user1&#39;)

要执行此语句,请执行此操作

EXEC(@DynamicSql);

答案 4 :(得分:0)

我认为最好的方法是构建动态SQL并添加查找以查看列是否存在并阻止列名称中的SQL注入。

declare @strDept nvarchar(10), @strUser nvarchar(30), 
        @sql nvarchar(300), @found smallint
set @strDept = 'f18'
set @strUser = 'Ted Lee'

set @found = (SELECT count(*) 
              FROM syscolumns 
              WHERE id=OBJECT_ID('table1') AND name=''+@strDept+'')

set @sql = 'select x, y, z from table1 where ' + @strDept + ' in ('''+@strUser+''')'

if @found = 1 exec (@sql)

SQL注入测试:请参阅SQL FIDDLE:http://www.sqlfiddle.com/#!6/df3f6/18/0

答案 5 :(得分:0)

另一种选择是在proc中使用一小部分替换。这仍然使用动态SQL,但您永远不会执行用户提供的值。

DECLARE @userSuppliedValue VARCHAR(50) = 'JOHNNY DROP TABLES'


DECLARE @substValue VARCHAR(50)

IF @userSuppliedValue = 'Table1'
  SET @substValue = 'Table1'

IF @userSuppliedValue = 'Table2'
  SET @substValue = 'Table2'

/*Repeat for N permutations*/

/* Throw an error if you think its necessary to do so when no match is found*/
IF @substValue IS NULL
  RAISERROR(1,1,'errah')

EXEC ('SELECT * FROM ' + @substValue)

答案 6 :(得分:0)

DECLARE @value varchar(10)  
SET @value = 'intStep'  
DECLARE @sqlText nvarchar(1000); 

SET @sqlText = N'SELECT ' + @value + ' FROM dbo.tblBatchDetail'
Exec (@sqlText)