2012-07-25 151 views
1

我已创建下面列出的查询。它运行时,我运行它。参数化数据库查询问题

string sortDir = (this.GridSortDirection == SortDirection.Descending ? " DESC" : " ASC"); 
int startIndex = 1; 
int endIndex = this.gvData.PageSize; 

SELECT RowNum, [ID], [Name], [Description], [DisplayIndex], [Status] 
FROM 
(
    SELECT [ID], [Name], [Description], [DisplayIndex], CASE WHEN Status = 1 THEN 'Active' ELSE 'Disabled' END AS [Status] , 
    ROW_NUMBER() OVER(ORDER BY [" + this.GridSortExpression + "]" + " " + sortDir + @")as 'RowNum' 
    FROM [MyDatabase].[dbo].[t_MyTable] s 

) as Info 
WHERE RowNum BETWEEN " + startIndex.ToString() + " AND " + endIndex.ToString() 

我试图将其重构为参数化查询格式,如下所示,但运行时出现错误。该错误指出sortDir附近存在语法错误。

string sql = @"SELECT RowNum, [ID], [Name], [Description], [DisplayIndex], [Status] 
FROM 
(
    SELECT [ID], [Name], [Description], [DisplayIndex], CASE WHEN Status = 1 THEN 'Active' ELSE 'Disabled' END AS [Status] , 
    ROW_NUMBER() OVER(ORDER BY @SortExpression @SortDir)as 'RowNum' 
    FROM [MyDatabase].[dbo].[t_MyTable] s 

) as Info 
WHERE RowNum BETWEEN @startIndex AND @endIndex"; 

cmd = new SqlCommand(sql, conn); 
cmd.Parameters.AddWithValue("@SortExpression", this.GridSortExpression); 
cmd.Parameters.AddWithValue("@SortDir", sortDir);     
cmd.Parameters.AddWithValue("@startIndex", startIndex); 
cmd.Parameters.AddWithValue("@endIndex", endIndex); 
da = new SqlDataAdapter(cmd); 
da.Fill(dt); 

我也尝试了以下无济于事......同样的错误消息

cmd = new SqlCommand(sql, conn); 
cmd.Parameters.AddWithValue("@SortExpression", this.GridSortExpression + " " + sortDir);      
cmd.Parameters.AddWithValue("@startIndex", startIndex); 
cmd.Parameters.AddWithValue("@endIndex", endIndex); 
da = new SqlDataAdapter(cmd); 
da.Fill(dt); 

任何人都可以参考我我的错误?

提前

回答

4

@SortExpression@SortDir非常感谢无法参数。它们是T-SQL语法的一部分,而不是值。您将不得不将它们留在命令文本字符串中。相比之下,@startIndex@endIndex是值,因此可以很好地作为参数。

如果您担心SQL注入,那么恐怕您将不得不编写自己的代码来验证this.GridSortExpressionsortDir的内容。例如:

  • 你可以检查sortDir等于或者"asc""desc"和拒绝其他任何东西。
  • 您可以从this.GridSortExpression中解析出列名称列表,然后将每个列表放在方括号中,然后再将列表重新放在一起。
1

可以使用CASE语句进行条件排序。

例如:

ORDER BY 
    CASE 
     WHEN @SortCol = 'a' THEN colA 
     WHEN @SortCol = 'b' THEN colB 
    END DESC 

可以进一步扩展该通过的方向进行排序。

ORDER BY 
    CASE WHEN @SortCol = 'a' AND @SortDir = 'ASC' THEN ColA END ASC 
    ,CASE WHEN @SortCol = 'a' AND @SortDir = 'DESC' THEN ColA END DESC 
    ,CASE WHEN @SortCol = 'b' AND @SortDir = 'ASC' THEN ColB END ASC 
    ,CASE WHEN @SortCol = 'b' AND @SortDir = 'DESC' THEN ColB END DESC 

我用这最后一次,我有一个@KeyDataColumn我想排序,按组,并在结果集返回。我没有重复这个逻辑3次,而是发现它更方便,可读和可扩展,以便将逻辑封装在子查询中。

SELECT 
    keyData.KeyDataColumn 
    ,COUNT(base.*) AS KeyDataCount 
FROM baseTable base 
    CROSS APPLY (
     SELECT 
      CASE 
       WHEN @KeyDataColumn = 'NextEvolution' THEN base.NextEvolution 
       WHEN @KeyDataColumn = 'TimesCaptured' THEN base.TimesCaptured 
       WHEN @KeyDataColumn = 'BattlesWon' THEN base.BattlesWon 
      END AS KeyDataColumn 
    ) keyData 
GROUP BY keyData.KeyDataColumn 
ORDER BY 
    CASE WHEN @SortDir = 'ASC' THEN keyData.KeyDataColumn END ASC 
    ,CASE WHEN @SortDir = 'DESC' THEN keyData.KeyDataColumn END DESC 
+0

谢谢你的跟进。非常有用和周到的答案 – Bengal 2012-08-10 14:12:44