2014-03-06 96 views
0

使用的SqlParameter我找不到如何在varchar列中使用IN運營商SqlParameter。請看看下面的@Mailbox參數:的Sql「IN」操作符與varchar字段

using (SqlCommand command = new SqlCommand()) 
{ 
    string sql = 
    @"select  
     ei.ID as InteractionID, 
     eo.Sentdate as MailRepliedDate 
     from  
     bla bla 
     where 
     Mailbox IN (@Mailbox)"; 
    command.CommandText = sql; 
    command.Connection = conn; 
    command.CommandType = CommandType.Text;      
    command.Parameters.Add(new SqlParameter("@Mailbox", mailbox));      
    SqlDataReader reader = command.ExecuteReader(); 
} 

我想這些字符串查詢不起作用。

string mailbox = "'[email protected]','[email protected]'" 
string mailbox = "[email protected],[email protected]" 

我也試圖改變查詢Mailbox IN('@Mailbox')
string mailbox = "[email protected],[email protected]"

有什麼建議?由於

+0

什麼是您的數據庫引擎? – Jodrell

+0

@Jodrell:因爲他使用'SqlCommand'和'SqlDataReader',它應該是sql-server。 –

+0

@TimSchmelter是哪個版本的SQL Server? – Jodrell

回答

2

這並不以這種方式工作。

可以參數列表中的每個值在IN條款:

string sql = 
    @"select  
     ei.ID as InteractionID, 
     eo.Sentdate as MailRepliedDate 
     from  
     bla bla 
     where 
     Mailbox IN ({0})"; 
string mailbox = "[email protected],[email protected]"; 
string[] mails = mailbox.Split(','); 
string[] paramNames = mails.Select((s, i) => "@tag" + i.ToString()).ToArray(); 
string inClause = string.Join(",", paramNames); 

using (var conn = new SqlConnection("ConnectionString")) 
using (SqlCommand command = new SqlCommand(sql, conn)) 
{ 
    for (int i = 0; i < paramNames.Length; i++) 
    { 
     command.Parameters.AddWithValue(paramNames[i], mails[i]); 
    } 
    conn.Open(); 
    using (SqlDataReader reader = command.ExecuteReader()) 
    { 
     // ... 
    } 
} 

摘自:https://stackoverflow.com/a/337792/284240

+0

爲我工作謝謝你 – cihata87

-1

爲什麼不只是concactenate你mailbox變量與sql字符串變量

0

由於您使用的MS SQL服務器,您有4種選擇,根據不同的版本。按優先順序列出。

1.傳遞一個複合值,並調用一個自定義的CLR或表值函數將其分解爲一個集合。 see here

您需要編寫自定義函數並在查詢中調用它。您還需要將該程序集加載到數據庫中,以使CLR可以作爲TSQL訪問。

如果您仔細閱讀了上面鏈接的所有Sommarskog's work,並且我建議您這樣做,您會發現如果性能和併發性非常重要,那麼您可能需要提供CLR函數來完成此任務。有關one possible implementation的詳細信息,請參閱下文。

2.使用表值參數。 see here

您將需要最新版本的MSSQL服務器。

3.傳遞多個參數。

您必須在語句中動態生成正確數量的參數。 Tim Schmelter's answer顯示了一種方法來做到這一點。

4.在客戶端生成動態SQL。我不建議你真的這樣做

你必須小心避免注入攻擊,並且從查詢計劃重用中受益的可能性會降低。

dont do it like this


一個可能的CLR實現。

using System; 
using System.Collections; 
using System.Data; 
using System.Data.SqlClient; 
using System.Data.SqlTypes; 
using Microsoft.SqlServer.Server; 

public class CLR_adam 
{ 
    [Microsoft.SqlServer.Server.SqlFunction(
     FillRowMethodName = "FillRow_char") 
    ] 
    public static IEnumerator CLR_charlist_adam(
     [SqlFacet(MaxSize = -1)] 
     SqlChars Input, 
     [SqlFacet(MaxSize = 255)] 
     SqlChars Delimiter 
     ) 
    { 
     return (
      (Input.IsNull || Delimiter.IsNull) ? 
      new SplitStringMulti(new char[0], new char[0]) : 
      new SplitStringMulti(Input.Value, Delimiter.Value)); 
    } 

    public static void FillRow_char(object obj, out SqlString item) 
    { 
     item = new SqlString((string)obj); 
    } 

    [Microsoft.SqlServer.Server.SqlFunction(
     FillRowMethodName = "FillRow_int") 
    ] 
    public static IEnumerator CLR_intlist_adam(
     [SqlFacet(MaxSize = -1)] 
     SqlChars Input, 
     [SqlFacet(MaxSize = 255)] 
     SqlChars Delimiter 
     ) 
    { 
     return (
      (Input.IsNull || Delimiter.IsNull) ? 
      new SplitStringMulti(new char[0], new char[0]) : 
      new SplitStringMulti(Input.Value, Delimiter.Value)); 
    } 

    public static void FillRow_int(object obj, out int item) 
    { 
     item = System.Convert.ToInt32((string) obj); 
    } 


    public class SplitStringMulti : IEnumerator 
    { 
     public SplitStringMulti(char[] TheString, char[] Delimiter) 
     { 
      theString = TheString; 
      stringLen = TheString.Length; 
      delimiter = Delimiter; 
      delimiterLen = (byte)(Delimiter.Length); 
      isSingleCharDelim = (delimiterLen == 1); 

      lastPos = 0; 
      nextPos = delimiterLen * -1; 
     } 

     #region IEnumerator Members 

     public object Current 
     { 
      get 
      { 
       return new string(
        theString, 
        lastPos, 
        nextPos - lastPos).Trim(); 
      } 
     } 

     public bool MoveNext() 
     { 
      if (nextPos >= stringLen) 
       return false; 
      else 
      { 
       lastPos = nextPos + delimiterLen; 

       for (int i = lastPos; i < stringLen; i++) 
       { 
        bool matches = true; 

        //Optimize for single-character delimiters 
        if (isSingleCharDelim) 
        { 
         if (theString[i] != delimiter[0]) 
          matches = false; 
        } 
        else 
        { 
         for (byte j = 0; j < delimiterLen; j++) 
         { 
          if (((i + j) >= stringLen) || 
           (theString[i + j] != delimiter[j])) 
          { 
           matches = false; 
           break; 
          } 
         } 
        } 

        if (matches) 
        { 
         nextPos = i; 

         //Deal with consecutive delimiters 
         if ((nextPos - lastPos) > 0) 
          return true; 
         else 
         { 
          i += (delimiterLen-1); 
          lastPos += delimiterLen; 
         } 
        } 
       } 

       lastPos = nextPos + delimiterLen; 
       nextPos = stringLen; 

       if ((nextPos - lastPos) > 0) 
        return true; 
       else 
        return false; 
      } 
     } 

     public void Reset() 
     { 
      lastPos = 0; 
      nextPos = delimiterLen * -1; 
     } 

     #endregion 

     private int lastPos; 
     private int nextPos; 

     private readonly char[] theString; 
     private readonly char[] delimiter; 
     private readonly int stringLen; 
     private readonly byte delimiterLen; 
     private readonly bool isSingleCharDelim; 
    } 
};