4

我需要一些关于我的 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 变量视为列名?

4

7 回答 7

7

您找不到有关如何执行此操作的指导的原因是这是一个非常糟糕的主意

迟早会有人传一个“列名” 1 ;drop database badidea。这将是所有相关人员的祝福。

阅读 SQL 注入,重新思考你的设计。

于 2013-08-21T14:46:06.240 回答
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 语句,它将与您运行的完全一样: SELECT x,y,z from table1 where f18 = 'Ted Lee'

EXEC (@SQL)
END
于 2013-08-21T17:20:36.777 回答
3

为什么要使列名动态化?你打算达到什么目标?您可以使用类似上述答案的动态查询,但注入攻击可能会开始。

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

于 2013-08-21T14:35:51.910 回答
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,其中 dept1 in ('user1')

要执行此语句,您可以这样做

EXEC(@DynamicSql);
于 2013-08-21T14:32:46.403 回答
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

于 2013-08-21T15:30:45.023 回答
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)
于 2013-08-21T17:15:28.907 回答
0
DECLARE @value varchar(10)  
SET @value = 'intStep'  
DECLARE @sqlText nvarchar(1000); 

SET @sqlText = N'SELECT ' + @value + ' FROM dbo.tblBatchDetail'
Exec (@sqlText)
于 2015-01-03T11:25:26.333 回答