Convert an array of integers for use in a SQL “IN” clause

前端 未结 8 2180
死守一世寂寞
死守一世寂寞 2021-01-05 03:44

Surely there is a framework method that given an array of integers, strings etc converts them into a list that can be used in a SQL \"IN\" clause?

e.g.

相关标签:
8条回答
  • 2021-01-05 04:14
    var inClause = "("
         + String.Join(",", values.Select(x => x.ToString()).ToArray()) 
         + ")";
    

    Note: You no longer need to call .ToArray() in .NET Framework 4. A new String.Join<T>(string separator, IEnumerable<string> values) method is added.

    0 讨论(0)
  • 2021-01-05 04:14

    You can use the String.Join method, like this:

    var str = "(" + string.Join(", ", Array.ConvertAll(values, v => v.ToString(CultureInfo.InvariantCulture)));
    

    Assuming that values is an array, Array.ConvertAll should be more efficient than LINQ with ToArray.

    0 讨论(0)
  • 2021-01-05 04:24

    If you don't have access to the .NET 3.5 extension methods, you can do this:

    StringBuilder sb = new StringBuilder();
    sb.Append('(');
    
    foreach (int i in values) {
        sb.Append(i).Append(',');
    }
    
    // remove final ,
    sb.Length -= 1;
    sb.Append(')');
    
    string inValue = sb.ToString();
    

    Which'll work on .NET 2

    0 讨论(0)
  • 2021-01-05 04:24

    Hey, great suggestions, just a slight modification below

    public static class IEnumerableExtensions
    {
        // reasonable to assume you will use this everywhere, not just
        // Sql statements, but log statements, anywhere you need to 
        // dump a list into a readable format!
        // 
        // HINT: extra credit: you can generalize this, and provide
        // specialized short hands that invoke the general method
        public static string ToCommaSeparatedString<T>(this IEnumerable<T> values)
        {
             // SIGH: so apparently this does not generate minimal
             // assembler on every machine, please note the following
             // is written for clarity, please feel free to substitute
             // your own favourite ultra-performance high-octance
             // string appender algorithm
             StringBuilder commaSeparated = new StringBuilder ();
             foreach (T value in values)
             {
                 // PERF: store format string as const
                 commaSeparated.AppendFormat ("{0}, ", value);
             }
             // PERF: store trim chars as static readonly array
             return commaSeparated.Trim (", ".ToCharArray ());
        }
    }
    
    ...
    // elsewhere in code
    List<int> myIdentifiers = new List<int> { 1, 2, 3, 4, 5, };
    string mySqlIdentifierList = myIdentifiers.ToCommaSeparatedList ();
    string mySqlStatementFormat = "SELECT * FROM [SomeTable] WHERE [Id] IN ({0})";
    string mySqlStatement = 
        string.format (mySqlStatementFormat, mySqlIdentifierList);
    ...
    
    0 讨论(0)
  • 2021-01-05 04:28

    If your list of integers is large, you may end up generating a string that is too long for your database to accept. E.g. I think the maximum length of a VARCHAR in SQL2000 is around 8K.

    So I have a set of helper method something like the sample below, which return an enumeration of strings, which can then be used as follows:

    List<int> idList = ...;
    using(SqlCommand command = ...)
    {
        ...
        foreach(string idString in ConcatenateValues(ids,",", maxLength, false))
        {
           command.Parameters[...] = idString;
           // or command.CommandText = "SELECT ... IN (" + idString + ")...";
           ... execute command ...
        }
    }
    

    The concatenate method might look something like the following:

    public static IEnumerable<string> ConcatenateValues(IEnumerable<int> values, string separator, int maxLength, bool skipDuplicates)
    {
        IDictionary<int, string> valueDictionary = null;
        StringBuilder sb = new StringBuilder();
        if (skipDuplicates)
        {
            valueDictionary = new Dictionary<int, string>();
        }
        foreach (int value in values)
        {
            if (skipDuplicates)
            {
                if (valueDictionary.ContainsKey(value)) continue;
                valueDictionary.Add(value, "");
            }
            string s = value.ToString(CultureInfo.InvariantCulture);
            if ((sb.Length + separator.Length + s.Length) > maxLength)
            {
                // Max length reached, yield the result and start again
                if (sb.Length > 0) yield return sb.ToString();
                sb.Length = 0;
            }
            if (sb.Length > 0) sb.Append(separator);
            sb.Append(s);
        }
        // Yield whatever's left over
        if (sb.Length > 0) yield return sb.ToString();
    }
    
    0 讨论(0)
  • 2021-01-05 04:35

    You can do this more efficiently using the following extension method:

        ///<summary>Appends a list of strings to a StringBuilder, separated by a separator string.</summary>
        ///<param name="builder">The StringBuilder to append to.</param>
        ///<param name="strings">The strings to append.</param>
        ///<param name="separator">A string to append between the strings.</param>
        public static StringBuilder AppendJoin(this StringBuilder builder, IEnumerable<string> strings, string separator) {
            if (builder == null) throw new ArgumentNullException("builder");
            if (strings == null) throw new ArgumentNullException("strings");
            if (separator == null) throw new ArgumentNullException("separator");
    
            bool first = true;
    
            foreach (var str in strings) {
                if (first)
                    first = false;
                else
                    builder.Append(separator);
    
                builder.Append(str);
            }
    
            return builder;
        }
    
        ///<summary>Combines a collection of strings into a single string.</summary>
        public static string Join<T>(this IEnumerable<T> strings, string separator, Func<T, string> selector) { return strings.Select(selector).Join(separator); }
        ///<summary>Combines a collection of strings into a single string.</summary>
        public static string Join(this IEnumerable<string> strings, string separator) { return new StringBuilder().AppendJoin(strings, separator).ToString(); }
    
    0 讨论(0)
提交回复
热议问题