2008-11-19 2 views
45

параметризованные запросы в .NET всегда выглядеть в примерах:параметризованных запросов с LIKE и в условиях

SqlCommand comm = new SqlCommand(@" 
    SELECT * 
    FROM Products 
    WHERE Category_ID = @categoryid 
", 
    conn); 
comm.Parameters.Add("@categoryid", SqlDbType.Int); 
comm.Parameters["@categoryid"].Value = CategoryID; 

Но я бегу в кирпичную стену, пытаясь сделать следующее:

SqlCommand comm = new SqlCommand(@" 
    SELECT * 
    FROM Products 
    WHERE Category_ID IN (@categoryids) 
     OR name LIKE '%@name%' 
", 
    conn); 
comm.Parameters.Add("@categoryids", SqlDbType.Int); 
comm.Parameters["@categoryids"].Value = CategoryIDs; 
comm.Parameters.Add("@name", SqlDbType.Int); 
comm.Parameters["@name"].Value = Name; 

Где

  • CategoryIDs через запятую список номеров "123456789" (без кавычек)
  • Имя является строкой, возможно, с одинарными кавычками и других плохих персонажей

Что такое правильный синтаксис для этого?

+0

В "IN" clasule необходимо указать любое значение в команде SQL. И добавьте в таблицу «Параметры» добавку. Если вы передадите значение строки в SQL через значение параметра, вы не должны бояться за SQL-инъекцию. – TcKs 2008-11-19 20:08:06

+0

Вы можете написать свой запрос как `WHERE name LIKE CONCAT ('%',?, '%')` – 2017-10-12 09:49:22

ответ

56

Предположим, что у вас есть идентификаторы категорий в целочисленном массиве, а Name - строка. Хитрость заключается в создании текста команды, позволяющего вводить все идентификаторы вашей категории в виде отдельных параметров и строить нечеткое соответствие имени. Чтобы сделать первый, мы используем цикл для построения последовательности имен параметров @ p0 через @ pN-1, где N - количество идентификаторов категории в массиве. Затем мы создаем параметр и добавляем его в команду с ассоциированным идентификатором категории как значение для каждого именованного параметра. Затем мы используем конкатенацию имени в самом запросе, чтобы разрешить нечеткий поиск по имени.

string Name = "someone"; 
int[] categoryIDs = new int[] { 238, 1138, 1615, 1616, 1617, 
           1618, 1619, 1620, 1951, 1952, 
           1953, 1954, 1955, 1972, 2022 }; 

SqlCommand comm = conn.CreateCommand(); 

string[] parameters = new string[categoryIDs.Length]; 
for(int i=0;i<categoryIDs.Length;i++) 
{ 
    parameters[i] = "@p"+i; 
    comm.Parameters.AddWithValue(parameters[i], categoryIDs[i]); 
} 
comm.Parameters.AddWithValue("@name",$"%{Name}%"); 
comm.CommandText = "SELECT * FROM Products WHERE Category_ID IN ("; 
comm.CommandText += string.Join(",", parameters) + ")"; 
comm.CommandText += " OR name LIKE @name"; 

Это полностью параметризованный запрос, который должен сделать ваш администратор базы данных счастливым. Я подозреваю, что, поскольку они являются целыми числами, хотя это не было бы большим риском для безопасности, просто для того, чтобы напрямую строить текст команды со значениями, но все же параметризуя имя. Если ваши идентификаторы категорий находятся в массиве строк, просто разделите массив на запятые, преобразуйте их в целое и сохраните в массиве integer.

Примечание: Я говорю массив и использую его в примере, но он должен работать для любой коллекции, хотя ваша итерация, вероятно, будет отличаться.

Оригинальная идея от http://www.tek-tips.com/viewthread.cfm?qid=1502614&page=9

10

Вам нужно «%» в значении параметра sql.

SqlCommand comm = new SqlCommand("SELECT * FROM Products WHERE Category_ID IN (@categoryid1, @categoryid2) OR name LIKE @name", conn); 
comm.Parameters.Add("@categoryid1", SqlDbType.Int); 
comm.Parameters["@categoryid1"].Value = CategoryID[0]; 
comm.Parameters.Add("@categoryid2", SqlDbType.Int); 
comm.Parameters["@categoryid2"].Value = CategoryID[1]; 
comm.Parameters.Add("@name", SqlDbType.Int); 
comm.Parameters["@name"].Value = "%" + Name + "%"; 
-2

не уверен, что это правильный путь, но это, как я делал это в Перед

список TempList = новый список

comm.Parameters.Add («@ categoryids» , SqlDbType.varchar); comm.Parameters ["@ categoryids"]. Value = string.join (",", templist.toarray())

+1

Нет. Вы не можете параметризовать список значений. Ну, вы можете, но он сравнит Category_ID с единственным значением * string * '1,2,3' вместо сравнения с каждым целым значением в списке. Это приведет к непредвиденным результатам. :-) – 2008-11-19 21:30:57

6

Этот подход не будет работать. Период.

Предложение IN ожидает список сам параметров, поэтому, когда вы связываете параметр один к нему, у вас есть шанс пройти в один значение.

Стройте свою строку оператора динамически, с точной суммой отдельных закладок, которые вы намерены передать, а затем добавьте параметры и привяжите значения к ним в цикле.

+0

Другим трюком является создание множества параметров в SQL и привязка значений повторно. Это неэлегантно, но оно работает, потому что IN (1,2,3) и IN (1,2,3, 1,2,3, 1,2) являются эквивалентными предикатами. – 2008-11-19 21:26:14

Смежные вопросы