2012-04-26 88 views
1

我在嘗試參數化ASP應用程序使用的現有C#類中的某些「動態」SQL構建時遇到了問題。環境是:如何使用C#參數化DB2 ODBC查詢?

  • 贏服務器2008
  • .NET 3.0
  • C#
  • DB2 9.x的([IBM] [CLI驅動程序] [DB2])

現有代碼只是將SQL與參數字符串串聯在一個長的SQL字符串中 - 這當然有SQL注入的風險。正如我的做法,每當我看到這一點時,我傾向於更改代碼以使用參數。但是,這個代碼我失敗了。我嘗試過「@」,我嘗試過「?」 - 後者是我所理解的ODBC所必需的。

下面是一個簡單的代碼片段(原諒我,如果我不格式化正確的 - 這是我的第一個問題),我已經編譯和運行:

private DataSet test(String schemaName) 
{ 
     String sortField = "TABLE_NAME.COLUMN_NAME"; 
     String sortDirection = "ASC"; 
     OdbcConnection conn = new OdbcConnection(); 
     DataSet ds = new DataSet(); 

     string connStr = ConfigurationManager.AppSettings[schemaName] + dbUser; 
     try 
     { 
      conn.ConnectionString = connStr; 
      OdbcCommand cmd = new OdbcCommand("SELECT * FROM TABLE_NAME ORDER BY ? ? "); 
      cmd.Connection = conn; 
      cmd.CommandType = CommandType.Text; 
      cmd.Parameters.Add(sortField); 
      cmd.Parameters.Add(sortDirection);        
      logger.log("cmd SQL = \t" + cmd.CommandText); 

      OdbcDataAdapter da = new OdbcDataAdapter(cmd); 
      da.Fill(ds); 

      return ds; 
     } 
     catch (Exception ex) 
     { 
      ex.Data.Add("Location:", "test()"); 
      ex.Data.Add("Connection", conn.ConnectionString); 
      logger.logException(ex); 
      throw ex; 
     } 
     finally 
     { 
      conn.Close(); 
     } 
    } 

日誌打印:

CMD SQL = SELECT * FROM TABLE_NAME ORDER BY? ?

其中TABLE_NAME當然是我查詢的表格。

我得到的回報是這樣(一些專有信息刪除:

異常出現在2012年4月26日下午12時29分41秒ERROR [42601] [IBM] [CLI 驅動程序] [ DB2] SQL0104N在「」之後發現了一個意外的令牌「?」 預期令牌可能包括:「MICROSECONDS MICROSECOND SECONDS SECOND MINUTES MINUTE HOURS」SQLSTATE = 42601 at System.Data.Odbc.OdbcConnection.HandleError(OdbcHandle hrHandle, RetCode retcode)連接驅動程序= {IBM DB2 ODBC DRIVER}; .....

不允許將其更改爲存儲過程。

不允許升級到更高版本的.NET。

不允許更改/升級ODBC驅動程序。

我所看到的告訴我,「?」參數未被替換。

我已經嘗試過AddWithValue(),我試過添加(OdbcType.VarChar).Value = sortField(或者那個效果)。

我很善於處理我的問題 - 所有的搜索和搜索都表明我上面的代碼應該可以工作,但到目前爲止我還沒有能夠用SQL中的參數替換變量。

在此先感謝。

+0

哦,我已經嘗試了 「新OdbcParameter(......)」 太。 – 2012-04-26 20:45:28

+0

我不相信你正在嘗試的是真實的參數。 「FieldName =?」是一個參數。在這種情況下,您將構建查詢爲:「... ORDER BY」+ sortField +「」+ sortDirection – Quintium 2012-04-26 20:46:10

+0

不是SQL參數,而是將C#參數替換爲SQL以防止SQL注入。我的例子是簡化的,但真正的查詢包含用戶可以輸入的字符串。我想保護SQL,防止父母給孩子起名爲「Bobby Tables」(「Robert」); DROP TABLE Students; - 「)。 – 2012-04-26 20:49:37

回答

1

?是一個意外標記的原因是因爲你在ORDER BY子句中使用它(我認爲這是不允許的)。

使用參數的原因是爲了減輕用戶輸入的風險。在構建查詢時,如果ORDER BY字段和方向不是通過用戶輸入發出的,則可以安全地構建具有串聯的查詢。

只有WHERE子句中使用?

OdbcCommand cmd = new OdbcCommand("SELECT * FROM TABLE_NAME WHERE ID = ? ORDER BY " + sortField + " " + sortDirection); 
+0

你說得對。我剛剛簡化了我的例子,太多了。 – 2012-04-26 21:11:31

+0

是的,一旦我使用「FieldName =?」在查詢的其餘部分,它開始按預期工作。現在我需要了解是否可以將列和模式名稱(兩者都是可變的)分開。我懷疑不是,但它們不是由用戶輸入提供的,並且它們是通過調用代碼提供的相對安全的。 – 2012-04-26 21:17:23

+0

我懷疑大多數ORM使用concat構建非用戶提供的部件,但是然後切換到用戶值的參數。我明白你想完成什麼,但我不認爲ODBC(它具有非常低的功能執行速度)將會支持你。 – mgnoonan 2012-04-26 21:21:20