Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Sparametryzuj klauzulę SQL IN

Możesz sparametryzować każdy wartość, więc coś takiego:

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 da ci:

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"

Nie, nie jest to otwarte na wstrzyknięcie SQL. Jedyny tekst wstrzykiwany do CommandText nie jest oparty na danych wejściowych użytkownika. Opiera się wyłącznie na zakodowanym na sztywno przedrostku „@tag” i indeksie tablicy. Indeks zawsze być liczbą całkowitą, nie jest generowany przez użytkownika i jest bezpieczny.

Wartości wprowadzone przez użytkownika są nadal umieszczane w parametrach, więc nie ma tam luki.

Edycja:

Pomijając kwestie wstrzykiwania, należy zwrócić uwagę, że konstruowanie tekstu polecenia w taki sposób, aby zawierał zmienną liczbę parametrów (jak wyżej) utrudnia SQL Serverowi korzystanie z buforowanych zapytań. Rezultatem jest to, że prawie na pewno tracisz wartość używania parametrów w pierwszej kolejności (w przeciwieństwie do zwykłego wstawiania ciągów predykatów do samego SQL).

Nie chodzi o to, że buforowane plany zapytań nie są wartościowe, ale IMO to zapytanie nie jest wystarczająco skomplikowane, aby zobaczyć z niego wiele korzyści. Chociaż koszty kompilacji mogą zbliżyć się (lub nawet przekroczyć) koszty wykonania, nadal mówisz o milisekundach.

Jeśli masz wystarczającą ilość pamięci RAM, spodziewam się, że SQL Server prawdopodobnie zapisze również w pamięci podręcznej plan dla typowej liczby parametrów. Przypuszczam, że zawsze można dodać pięć parametrów i niech nieokreślone tagi mają wartość NULL - plan zapytania powinien być taki sam, ale wydaje mi się to dość brzydkie i nie jestem pewien, czy warto by było dokonać mikrooptymalizacji (chociaż na Stack Overflow – może być warto).

Ponadto SQL Server 7 i nowsze będą automatycznie parametryzować zapytania, więc używanie parametrów nie jest tak naprawdę konieczne z punktu widzenia wydajności — jest to jednak krytyczne z punktu widzenia bezpieczeństwa - zwłaszcza w przypadku takich danych wprowadzanych przez użytkownika.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Co to jest @@TEXTSIZE w programie SQL Server?

  2. Jak mogę zablokować tabelę podczas odczytu przy użyciu Entity Framework?

  3. Najlepszy sposób na przechowywanie czasu (gg:mm) w bazie danych

  4. Jaki jest punkt początkowego katalogu w parametrach połączenia programu SQL Server?

  5. Funkcja podziału w SQL Server 2008