2012-07-25 153 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