8
votes

Convertir une gamme d'entiers pour une utilisation dans une clause SQL "dans"

Il existe sûrement une méthode-cadre donnée à une matrice d'entiers, de chaînes, etc. les convertit dans une liste pouvant être utilisée dans une clause SQL " dans "?

E.g. xxx

irait à xxx


0 commentaires

8 Réponses :


17
votes
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.

13 commentaires

Qui produira une liste , pas une chaîne qui peut être utilisée dans une déclaration SQL


TheCoop: J'ai mal compris votre question. Mis à jour.


@CheCoop: Non, ça ne va pas. @Mehrdad: ça ne compilera pas; string.join prend seulement un tableau.


@Slaks: Je pense que Mehrdad utilise VS2010, qui résoudra cela.


Comme utilisera WHRAY.CONTERTALL (valeurs, convertir.tostring)


Slaks: Facile à réparer. Ajouter un toarray.


@CheCoop: Exactement; voir ma réponse. @Mehrdad: Je sais; Je te rappelais.


Aussi peut-être utiliser String.Format afin que les chaînes Tempat sont créées (dépend de la fréquence à laquelle cela sera appelé, bien sûr ...)


thecoop: je ne peux pas voir comment string.format aide ici. Connaissez-vous le nombre d'éléments à l'avance? Aussi, string.format est généralement la méthode la moins efficace car elle nécessite l'analyse de la chaîne de format.


@Mehrdad: "(" + str + ")" crée des objets à chaîne temporaire - Vous ne voudrez peut-être pas faire cela s'il est utilisé beaucoup de fois


TheCoop: Vous devriez lire l'un des nombreux blogs couvrant la concaténation de chaînes en profondeur. "(" + STR + ")" est résolu à un Single appel à string.concat en passant les trois cordes comme arguments. Il alloue un seul tampon pour maintenir la chaîne résultante.


@Cethecoop - "(" + str + ")" est converti en système.string :: Concat (chaîne, chaîne, chaîne) qui ne doit pas créer de chaînes temporaires supplémentaires au-delà de la solution String.Format créerait également avec les mêmes paramètres . Je viens de vérifier cela avec ilasme.


Excusez-moi, je suis débutant et j'ai essayé de le faire et d'une manière ou d'une autre, cela ne fonctionne pas. Qu'est-ce que je rate? en utilisant (mysqlCommand com = nouveau mysqlCommand ("Select * de Sample_Table où unique_id in (@unique_id)", con)) {com.parameters.add ("@ group_id", mysqldbtype.string) .value = incarce; }



5
votes

Si vous n'avez pas accès aux méthodes d'extension .NET 3.5, vous pouvez le faire:

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();


0 commentaires


2
votes

Ceci pourrait être fait dans une ligne aussi

public string ToInStatement(this int[] values) {
    string[] stringValues = 
       Array.ConvertAll<int, string>(values, Convert.ToString);
    string result = "(" + String.Join(",", stringValues) + ")";
    return result;
 }


0 commentaires

0
votes

Hey, de grandes suggestions, juste une légère modification ci-dessous

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);
...


1 commentaires

Il serait plus rapide d'appeler deux fois d'appeler deux fois et ne pas analyser la chaîne de format à chaque fois. Il serait également plus rapide de vérifier si vous faites le premier article et, si vous êtes, n'ajoutez pas la virgule.



0
votes

Vous pouvez le faire plus efficacement en utilisant la méthode d'extension suivante: xxx


0 commentaires

0
votes
/// <summary>
/// Converts an array of integers into a string that may be used in a SQL IN expression.
/// </summary>
/// <param name="values">The array to convert.</param>
/// <returns>A string representing the array as a parenthetical comma-delemited list. If the array
/// is empty or missing, then "(null)" is returned.</returns>
public static string ToSqlInList(int[] values)
{
    if (values == null || values.Length == 0)
        return "(null)";  // In SQL the expression "IN (NULL)" is always false.

    return string.Concat("(", string.Join(",", Array.ConvertAll<int, string>(values,x=>x.ToString())), ")");
}

0 commentaires

1
votes

Si votre liste d'entiers est grande, vous risquez de générer une chaîne trop longue pour que votre base de données soit acceptée. Par exemple. Je pense que la longueur maximale d'un Varcharne dans SQL2000 est d'environ 8k.

J'ai donc un ensemble de méthode d'assistance quelque chose comme l'échantillon ci-dessous, qui renvoie une énumération de chaînes, qui peuvent ensuite être utilisées comme suit: p>

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();
}


2 commentaires

Il ne met pas la corde dans une colonne; Il construit une clause dans . Lisez la question.


Cette technique peut également être utilisée pour une clause en clause.