2011-12-27 47 views
2

這就是我試圖&失敗:如何使用IN sql關鍵字建立參數化查詢?

 string sql = "... WHERE [personID] IN (@sqlIn) ..."; 
     string sqlIn = "1,2,3,4,5"; 
     SqlCeCommand cmd.Parameters.Add("@sqlIn", SqlDbType.NText).Value = sqlIn; 

     SqlCeDataAdapter da = new SqlCeDataAdapter(cmd); 
     da.Fill(ds); // > Error 

錯誤的詳細信息:

的ntext和image數據類型不能使用WHERE,HAVING,GROUP BY,打開,或IN子句時除外這些數據類型與LIKE或IS NULL謂詞一起使用。

無法將所有ID作爲一個參數傳遞嗎?我應該一個一個添加所有的ID嗎?

P.S:Notice SqlCE

+0

清理你的例子也有什麼sqlIn – MethodMan 2011-12-27 15:49:53

+0

的代碼實際上是比較PERSONID到的「1,2,3,4,5」整個字符串,而不是反對用逗號分隔每個項目的價值。 – 2011-12-27 15:53:09

回答

5

您不能將它作爲單個參數進行參數化。您的查詢是做對值「中」,所以基本上是:

... Where personId = '1,2,3,4,5' 

(給予或採取一個參數)。這是通常也是一個無效或次優平等測試,當然不是你想要查詢。

選項;

  • 使用原始串聯:往往涉及SQL注入風險,並允許完整的SQL服務器上查詢差計劃重新使用
  • :使用UDF到完整的SQL服務器上,使用上拆單PARAM
  • 一個TVP
  • 添加參數動態,並添加各種@參數3等的TSQL

最後一個是最可靠的,而「短小精悍點網」內置了一個功能,爲你做這個(因爲它通常是需要的):

int[] ids = ... 
var rows = conn.Query<SomeType>(
    @"... Where Id in @ids", 
    new { ids }).ToList(); 

此,當通過運行短小精悍點網,將增加每個項目的參數在「IDS」,給它正確的價值等,並固定SQL所以它執行,例如:

"... Where Id in (@ids0, @ids1, @ids2)" 

+0

感謝您的好解釋! – 2011-12-28 07:54:13

3

(如果在「IDS」是3項),你需要用逗號分割的sqlIn串,每個轉換爲整數,並手動建立報表。

string sqlIn = "1,2,3,4,5"; 
    string inParams = sqlIn.Split(','); 
    List<string> paramNames = new List<string>(); 
    for(var i = 0; i < inParams.Length; ++i){ 
     string paramName = "@param" + i.ToString(); 
     SqlCeCommand cmd.Parameters.Add(paramName, SqlDbType.Int).Value = int.Parse(inParams[i]); 
     paramNames.Add(paramName); 
    } 

    string sql = "... WHERE [personID] IN (" + 
     string.Join(",", paramNames) + 
     ") ..."; 
+0

我剛注意到Marc的回答。他的建議更好。有ORM使這個問題不成問題。 SubSonic,EF,nHibernate,Dapper等 – 2011-12-27 16:07:06

+1

我會用這個更簡單的版本 – 2011-12-28 07:53:45