2009-03-16 18 views
6

Jestem w trakcie konwersji kilku zapytań, które zostały zakodowane na stałe w aplikacji i zbudowane w locie do sparametryzowanych zapytań. Mam problemy z jednym konkretnym zapytaniu, który ma in klauzuli:C# Sparametryzowane zapytanie MySQL z `in` klauzula

UPDATE TABLE_1 SET STATUS = 4 WHERE ID IN (1, 14, 145, 43); 

Pierwszy parametr jest proste, jak to tylko normalny parametr:

MySqlCommand m = new MySqlCommand("UPDATE TABLE_1 SET STATUS = ? WHERE ID IN (?);"); 
m.Parameters.Add(new MySqlParameter("", 2)); 

Jednak drugi parametr jest lista liczb całkowitych reprezentujących identyfikatory wierszy wymagających aktualizacji. Jak przekazać listę liczb całkowitych dla pojedynczego parametru? Ewentualnie, w jaki sposób skonfigurować tę kwerendę, aby nie musieć jej kompletnie budować za każdym razem, gdy ją wywołasz, i zapobiegać atakom SQL injection?

+0

duplikat http://stackoverflow.com/questions/337704/parameterizing-a-sql-in-clause (chociaż to serwer SQL zamiast mysql , ale wydaje się, że jest inaczej). –

+0

Oferowane tam rozwiązanie uznano za niesamowicie wolne, chociaż odpowiada na drugą połowę mojego pytania. – Elie

+0

Dostępnych jest * wiele * oferowanych rozwiązań. Przyjęta odpowiedź nie jest popularna. –

Odpowiedz

4

Można budować zapytania sparametryzowane „w locie” na podstawie (przypuszczalnie) zmienną liczbę parametrów i iteracyjne nad tym, by przekazać je w

Tak, coś takiego:.

List foo; // assuming you have a List of items, in reality, it may be a List<int> or a List<myObject> with an id property, etc. 

StringBuilder query = new StringBuilder("UPDATE TABLE_1 SET STATUS = ? WHERE ID IN (?") 
for(int i = 1; i++; i < foo.Count) 
{ // Bit naive 
    query.Append(", ?"); 
} 

query.Append(");"); 

MySqlCommand m = new MySqlCommand(query.ToString()); 
for(int i = 1; i++; i < foo.Count) 
{ 
    m.Parameters.Add(new MySqlParameter(...)); 
} 
+0

Właśnie o tym myślałem. Ale czy uzyskałabym korzyści wydajności związane z przechowywanie sparametryzowanych zapytań, jeśli to zrobiłem? – Elie

+0

Ado.Net sugeruje najlepszą wydajność poprzez stworzenie nowego połączenia, użycie go raz i wyrzucenie go - przynajmniej dla innych silników SQL; W końcu silnik zapytań mógłby zoptymalizować na podstawie ciągu zapytania, aby je ponownie wykorzystać ... –

2

Nie można używać parametrów dla klauzuli IN.

-1

Proponuję utworzyć funkcję (zakładając, że mysql obsługuje funkcje zdefiniowane przez użytkownika), aby przełamać parametr, aby zwrócić tabelę.

0

Pętla zaokrągla listę liczb całkowitych i wykonuje indywidualne aktualizacje.

MSSQL 2008 oferuje parametry tabelaryczne, aby uniknąć tego problemu, nie jestem świadomy żadnej podobnej funkcjonalności w MySQL.

+0

To byłoby niewiarygodnie nieefektywne, biorąc pod uwagę, że to zapytanie może, w niektórych przypadkach, zawierać tysiące elementów w klauzuli IN. – Elie

+0

Czy nie ma ograniczenia liczby elementów, które można mieć w klauzuli IN? – Svish

5

Nie jest to możliwe w MySQL. Można utworzyć wymaganą liczbę parametrów i wykonać ZAKTUALIZACJĘ ... IN (?,?,?,?). Zapobiega to atakom wtryskowym (ale nadal wymaga przebudowania zapytania dla każdej liczby parametrów).

Innym sposobem jest przekazanie łańcucha oddzielonego przecinkami i przeanalizowanie go.

1

Stare pytanie, ale w przypadku gdy ktoś natknie to za pośrednictwem Google, oto co używam:

int status = 4; 
string ids = "1,14,145,43";  

m.Parameters.AddWithValue("@Status", status); 
m.Parameters.AddWithValue("@IDs", ids); 

UPDATE TABLE_1 SET STATUS = @Status WHERE FIND_IN_SET(ID, @IDs) > 0; 

Uwaga: FIND_IN_SET jest mySQL specyficzne funkcje.

kredytowe, gdy kredyt jest spowodowane: Patrz na to pytanie: Add List<int> to a mysql parameter

Powiązane problemy