Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Paramétrer une clause SQL IN

Vous pouvez paramétrer chaque valeur, donc quelque chose comme :

string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" };
string cmdText = "SELECT * FROM Tags WHERE Name IN ({0})";

string[] paramNames = tags.Select(
    (s, i) => "@tag" + i.ToString()
).ToArray();

string inClause = string.Join(", ", paramNames);
using (SqlCommand cmd = new SqlCommand(string.Format(cmdText, inClause))) {
    for(int i = 0; i < paramNames.Length; i++) {
       cmd.Parameters.AddWithValue(paramNames[i], tags[i]);
    }
}

Ce qui vous donnera :

cmd.CommandText = "SELECT * FROM Tags WHERE Name IN (@tag0, @tag1, @tag2, @tag3)"
cmd.Parameters["@tag0"] = "ruby"
cmd.Parameters["@tag1"] = "rails"
cmd.Parameters["@tag2"] = "scruffy"
cmd.Parameters["@tag3"] = "rubyonrails"

Non, ce n'est pas ouvert à l'injection SQL. Le seul texte injecté dans CommandText n'est pas basé sur l'entrée de l'utilisateur. Il est uniquement basé sur le préfixe "@tag" codé en dur et sur l'index d'un tableau. L'index sera toujours être un nombre entier, n'est pas généré par l'utilisateur et est sûr.

Les valeurs saisies par l'utilisateur sont toujours insérées dans les paramètres, il n'y a donc aucune vulnérabilité ici.

Modifier :

Indépendamment des soucis d'injection, prenez soin de noter que la construction du texte de la commande pour accueillir un nombre variable de paramètres (comme ci-dessus) entrave la capacité du serveur SQL à tirer parti des requêtes mises en cache. Le résultat net est que vous perdez presque certainement la valeur de l'utilisation des paramètres en premier lieu (par opposition à la simple insertion des chaînes de prédicat dans le SQL lui-même).

Non pas que les plans de requête mis en cache ne soient pas utiles, mais IMO cette requête n'est pas assez compliquée pour en tirer beaucoup d'avantages. Bien que les coûts de compilation puissent approcher (voire dépasser) les coûts d'exécution, vous parlez toujours de millisecondes.

Si vous disposez de suffisamment de RAM, je m'attends à ce que SQL Server mette également en cache un plan pour le nombre commun de paramètres. Je suppose que vous pouvez toujours ajouter cinq paramètres et laisser les balises non spécifiées être NULL - le plan de requête devrait être le même, mais cela me semble assez moche et je ne suis pas sûr que cela vaille la micro-optimisation (bien que, sur Stack Overflow - cela peut très bien en valoir la peine).

De plus, SQL Server 7 et les versions ultérieures paramétreront automatiquement les requêtes. L'utilisation de paramètres n'est donc pas vraiment nécessaire du point de vue des performances. Elle est cependant critique. du point de vue de la sécurité - en particulier avec des données saisies par l'utilisateur comme celle-ci.