sql >> Database >  >> RDS >> Sqlserver

Een SQL IN-component parametriseren

U kunt elk parametriseren waarde, dus zoiets als:

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

Wat je zal geven:

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"

Nee, dit staat niet open voor SQL-injectie. De enige ingevoegde tekst in CommandText is niet gebaseerd op gebruikersinvoer. Het is uitsluitend gebaseerd op het hardcoded "@tag" voorvoegsel en de index van een array. De index zal altijd moet een geheel getal zijn, wordt niet door de gebruiker gegenereerd en is veilig.

De door de gebruiker ingevoerde waarden worden nog steeds in parameters gestopt, dus daar is geen kwetsbaarheid.

Bewerken:

Afgezien van de zorgen over de injectie, moet u er rekening mee houden dat het construeren van de opdrachttekst voor een variabel aantal parameters (zoals hierboven) het vermogen van de SQL-server om te profiteren van in de cache opgeslagen query's belemmert. Het netto resultaat is dat je vrijwel zeker de waarde verliest van het gebruik van parameters in de eerste plaats (in tegenstelling tot alleen het invoegen van de predikaatstrings in de SQL zelf).

Niet dat queryplannen in de cache niet waardevol zijn, maar IMO is deze query lang niet ingewikkeld genoeg om er veel voordeel uit te halen. Hoewel de compilatiekosten de uitvoeringskosten kunnen benaderen (of zelfs overschrijden), heb je het nog steeds over milliseconden.

Als je genoeg RAM hebt, zou ik verwachten dat SQL Server waarschijnlijk ook een plan voor de algemene tellingen van parameters in de cache zou opslaan. Ik veronderstel dat je altijd vijf parameters kunt toevoegen en de niet-gespecificeerde tags NULL kunt laten zijn - het queryplan zou hetzelfde moeten zijn, maar het lijkt me behoorlijk lelijk en ik weet niet zeker of het de micro-optimalisatie waard is (hoewel, op Stack Overflow - het kan de moeite waard zijn).

Ook zullen SQL Server 7 en hoger zoekopdrachten automatisch parametreren, dus het gebruik van parameters is niet echt nodig vanuit het oogpunt van prestaties - het is echter kritiek vanuit een veiligheidsstandpunt - vooral met door de gebruiker ingevoerde gegevens zoals deze.



  1. 3 manieren om rijen met kleine letters te vinden in SQLite

  2. PostgreSQL BESCHRIJVING TABEL Equivalent

  3. Het verschil begrijpen tussen BEHALVE en NIET IN operators

  4. Onze meest populaire databaseblogposts in 2017