sql >> Database teknologi >  >> RDS >> Sqlserver

Parametrér en SQL IN-sætning

Du kan parametrere hver værdi, så noget som:

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

Hvilket vil give dig:

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"

Nej, dette er ikke åbent for SQL-injektion. Den eneste injicerede tekst i CommandText er ikke baseret på brugerinput. Det er udelukkende baseret på det hårdkodede "@tag"-præfiks og indekset for et array. Indekset vil altid være et heltal, er ikke brugergenereret og er sikkert.

De brugerindtastede værdier er stadig fyldt i parametre, så der er ingen sårbarhed der.

Rediger:

Bortset fra indsprøjtningsproblemer, skal du være opmærksom på, at konstruering af kommandoteksten til at rumme et variabelt antal parametre (som ovenfor) hindrer SQL-serverens evne til at drage fordel af cachelagrede forespørgsler. Nettoresultatet er, at du næsten helt sikkert mister værdien af ​​at bruge parametre i første omgang (i modsætning til blot at indsætte prædikatstrengene i selve SQL'en).

Ikke at cachelagrede forespørgselsplaner ikke er værdifulde, men IMO er denne forespørgsel ikke nær kompliceret nok til at se meget fordel af det. Selvom kompileringsomkostningerne kan nærme sig (eller endda overstige) eksekveringsomkostningerne, taler du stadig millisekunder.

Hvis du har nok RAM, ville jeg forvente, at SQL Server sandsynligvis også ville cache en plan for de almindelige optællinger af parametre. Jeg formoder, at du altid kan tilføje fem parametre og lade de uspecificerede tags være NULL - forespørgselsplanen burde være den samme, men det virker ret grimt for mig, og jeg er ikke sikker på, at det ville være mikrooptimeringen værd (selvom, på Stack Overflow - det kan sagtens være det værd).

Også SQL Server 7 og nyere vil automatisk parametrere forespørgsler, så brug af parametre er egentlig ikke nødvendigt ud fra et ydeevnesynspunkt - det er dog kritisk fra et sikkerhedssynspunkt - især med brugerinputtede data som denne.



  1. Sådan tilføjes fremmednøgle i SQL?

  2. Regneark vs. databaser:Er det tid til at skifte? Del 2

  3. SQL VÆLG MIN

  4. Hvordan fjerner man en unik begrænsning i SQL?