我创建了下面列出的查询。它在我运行时有效。
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);
任何人都可以向我推荐我的错误吗?
非常感谢提前
答案 0 :(得分:4)
@SortExpression
和@SortDir
无法参数化。它们是T-SQL语法的一部分,而不是值。您必须将它们保留在命令文本字符串中。相比之下,@startIndex
和@endIndex
是值,因此可以作为参数使用。
如果您担心SQL注入,那么我担心您必须编写自己的代码来验证this.GridSortExpression
和sortDir
的内容。例如:
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