2013-12-03 2 views
5

У меня есть список ключевых слов, которые я храню в списке.Параметрированный динамический SQL-запрос

Для выборки записей из таблицы, я использую следующий запрос:

sqlBuilder.Append("SELECT name, memberid FROM members WHERE"); 
StringBuilder sqlBuilder = new StringBuilder(); 
foreach (string item in keywords) 
      { 
      sqlBuilder.AppendFormat(" LOWER(Name) LIKE '%{0}%' AND", item); 
      } 
string sql = sqlBuilder.ToString(); 

Как вы могли заметить, мой запрос уязвим к SQL-инъекции, таким образом, я хочу использовать параметры с помощью SqlCommand(). Я попытался следующие, но по-прежнему не работает:

foreach (string item in keywords) 
      {  
       sqlBuilder.AppendFormat(" LOWER(Name) LIKE '%' + @searchitem + '%' AND", item); 
       SqlCommand cmd = new SqlCommand(sqlBuilder.ToString()); 
       cmd.Parameters.AddWithValue("@searchitem",item); 
      } 

Где я мог бы сделать ошибку, или, вернее, как я должен есть по этому поводу?

+1

Потому что каждый раз, когда вы перебирать свой 'keywords', вы создать новый' SqlCommand'. Я думаю, вы должны использовать 'AppendFormat' в своем цикле' foreach', затем создать 'SqlCommand' и добавить свои параметры вне вашего цикла foreach. –

+1

Я предлагаю распечатать cmd.CommandText, вы увидите, что это не хорошо сформированный SQL-запрос (вы все делаете внутри своего цикла). Кроме того, подстановочный знак будет лучше сочетаться с значением параметра. –

ответ

13

Вы делаете кое-что здесь не так:

  • Вы отдаете все параметры еще такое же имя @searchitem. Это не сработает. Параметры должны иметь уникальные имена.
  • Вы создаете новый SqlCommand для каждого элемента. Это не сработает. Создайте SqlCommand один раз в начале цикла, а затем установите CommandText, как только вы закончите создание SQL.
  • Ваш SQL заканчивается AND, что является недопустимым синтаксисом.

Улучшение предложения (не является неправильным само по себе, но не лучшая практика либо):

  • Как Фредерик предложил, обычный способ поставить % маркеров в параметре, а не делать конкатенации внутри SQL.
  • Если вы явно не используете учетную запись для вашей базы данных, сравнение должно быть нечувствительным к регистру. Таким образом, вам может не понадобиться LOWER.

Пример кода:

SqlCommand cmd = new SqlCommand(); 
StringBuilder sqlBuilder = new StringBuilder(); 
sqlBuilder.Append("SELECT name, memberid FROM members "); 

var i = 1; 
foreach (string item in keywords) 
{ 
    sqlBuilder.Append(i == 1 ? " WHERE " : " AND "); 
    var paramName = "@searchitem" + i.ToString(); 
    sqlBuilder.AppendFormat(" Name LIKE {0} ", paramName); 
    cmd.Parameters.AddWithValue(paramName, "%" + item + "%"); 

    i++; 
} 
cmd.CommandText = sqlBuilder.ToString(); 
+0

Хорошие предложения. Я покончил с частью «И». Кроме того, я не использую сортировку db, чувствительную к регистру, поэтому я думаю, что я покончу с ключевым словом 'LOWER'. Как я могу использовать маркеры '%' в параметре? – mutiemule

+0

@mutiemule: Я добавил пример кода. Это помогает? – Heinzi

+0

Помогает много, но все равно никаких результатов. Когда я просматриваю код, запрос будет 'SELECT name, memberid FROM members WHERE Name LIKE @ searchitem1 AND Name LIKE @ searchitem2'. Когда я копирую это в редактор запросов и вручную вводим ключевые слова для поиска как 'SELECT name, memberid FROM members WHERE Name LIKE '% john%' AND Name LIKE '% smith%'', он возвращает результаты. В чем может быть проблема? – mutiemule

3

Не ставьте подстановочные символы в строке запроса, но добавить их в свой параметре-значение:

sql = "SELECT name FROM members WHERE Name LIKE @p_name"; 
... 
cmd.Parameters.AddWithValue("@p_name", "%" + item + "%"); 

При добавлении подстановочных символов внутри вашей строки запроса, параметр будет сбежавшим, но подстановочные символы не будут; что приведет к запросу, который отправляется в БД, который выглядит следующим образом:

SELECT name FROM members WHERE Name LIKE %'somename'% 

, что явно не так.

Рядом с этим вы создаете SqlCommand в цикле, который не является необходимым. Кроме того, вы создаете параметры с уникальным именем, так как вы добавляете их в цикл, и параметр всегда имеет одно и то же имя. Вы также должны удалить последнее ключевое слово И, когда вы выходите из цикла.

+2

Действительный момент, но это * не * причина, почему его запрос не работает. – Heinzi

+0

Обратите внимание, что я использую sqlbuilder. Попытался получить эту работу в sqlbuilder безрезультатно. – mutiemule

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