sql >> Databáze >  >> RDS >> Sqlserver

Parametrizujte klauzuli SQL IN

každý můžete parametrizovat hodnotu, takže něco jako:

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

Což vám dá:

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"

Ne, toto není otevřené pro SQL injection. Jediný text vložený do CommandTextu není založen na vstupu uživatele. Je založen výhradně na pevně zakódované předponě „@tag“ a indexu pole. Index bude vždy být celé číslo, není vygenerováno uživatelem a je bezpečné.

Hodnoty zadané uživatelem jsou stále nacpané do parametrů, takže zde není žádná zranitelnost.

Upravit:

Pomineme-li obavy z injekce, všimněte si, že sestavení textu příkazu tak, aby vyhovovalo proměnlivému počtu parametrů (jak je uvedeno výše), brání SQL serveru ve schopnosti využívat dotazy uložené v mezipaměti. Čistým výsledkem je, že téměř jistě ztratíte hodnotu používání parametrů na prvním místě (na rozdíl od pouhého vkládání predikátových řetězců do samotného SQL).

Ne, že by plány dotazů v mezipaměti nebyly cenné, ale IMO tento dotaz není ani zdaleka tak komplikovaný, aby z něj bylo vidět mnoho výhod. I když se náklady na kompilaci mohou přiblížit (nebo dokonce překročit) náklady na provedení, stále mluvíte o milisekundách.

Pokud máte dostatek paměti RAM, očekával bych, že SQL Server pravděpodobně uloží do mezipaměti plán pro běžné počty parametrů. Předpokládám, že byste mohli vždy přidat pět parametrů a nechat nespecifikované značky být NULL - plán dotazů by měl být stejný, ale zdá se mi to docela ošklivé a nejsem si jistý, zda by to stálo za mikrooptimalizaci (ačkoli, na Stack Overflow – může to stát za to).

SQL Server 7 a novější také automaticky parametrizuje dotazy, takže použití parametrů není z hlediska výkonu ve skutečnosti nutné – je však kritické z bezpečnostního hlediska – zejména s daty zadávanými uživateli, jako je tato.



  1. Co je index v SQL?

  2. SQL Server SELECT do existující tabulky

  3. Pivot na více sloupců pomocí Tablefunc

  4. Příklady LOG() v SQL Server