在varchar字段上使用SqlParameter的Sql“IN”运算符

时间:2014-03-06 09:54:48

标签: sql sql-server sql-server-2008 c#-4.0 sql-in

我找不到如何在IN列上使用SqlParameter运算符和varchar。请查看以下@Mailbox参数:

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 = "'abc@abc.com','def@def.com'"
string mailbox = "abc@abc.com,def@def.com"

我也尝试过更改查询Mailbox IN('@Mailbox')
string mailbox = "abc@abc.com,def@def.com"

有什么建议吗?感谢

3 个答案:

答案 0 :(得分:2)

这不起作用。

您可以在IN子句中参数化列表中的每个值:

string sql =
  @"select    
         ei.ID as InteractionID,
         eo.Sentdate as MailRepliedDate
      from    
         bla bla
      where  
         Mailbox IN ({0})";
string mailbox = "abc@abc.com,def@def.com";
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

答案 1 :(得分: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;
    }
};

答案 2 :(得分:-1)

为什么不将mailbox变量与sql字符串变量重新同步