参数化数据库查询问题

时间:2012-07-25 19:16:44

标签: .net tsql c#-4.0

我创建了下面列出的查询。它在我运行时有效。

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);

任何人都可以向我推荐我的错误吗?

非常感谢提前

2 个答案:

答案 0 :(得分:4)

@SortExpression@SortDir无法参数化。它们是T-SQL语法的一部分,而不是值。您必须将它们保留在命令文本字符串中。相比之下,@startIndex@endIndex是值,因此可以作为参数使用。

如果您担心SQL注入,那么我担心您必须编写自己的代码来验证this.GridSortExpressionsortDir的内容。例如:

  • 您可以检查sortDir是否等于"asc""desc"并拒绝其他任何内容。
  • 您可以从this.GridSortExpression中解析出列名列表,然后将每个列名放在方括号中,然后再将列表重新组合在一起。

答案 1 :(得分: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