Экранирование специальных символов в операторе SQL LIKE с использованием параметров sql
У меня есть таблица с продуктами. Мне нужно сделать запрос, чтобы найти все соответствующие результаты для пользовательского ввода значения. я использую SqlParameter
для вставки входов.
SqlCommand findProcutsByPattern = new SqlCommand(
"SELECT *" +
" FROM [Products]" +
" WHERE ProductName LIKE @pattern", connection);
findProcutsByPattern.Parameters.AddWithValue("@pattern", '%' + pattern + '%');
Проблема возникает, когда строка ввода пользователя содержит "_" или "%", поскольку они интерпретируются как специальные символы. С другой стороны, учитывая это:
Командные объекты используют параметры для передачи значений в операторы SQL или хранимые процедуры, обеспечивая проверку и проверку типа. В отличие от текста команды, ввод параметров рассматривается как буквальное значение, а не как исполняемый код.
У меня не должно быть таких проблем. Нужно ли заменить / экранировать все '_' и '%' во входной строке или есть более элегантное решение. Я хочу, чтобы входные данные рассматривались как буквальные.
У меня есть несколько записей в таблице, которые включают в себя специальные символы в имени (N_EW, N\EW, N%EW, N"EW, N'EW). Указывая \, " и ", так как ввод работает нормально (считает их как литералы).
4 ответа
У вас есть два варианта:
заключить их в
[
а также]
, Так:where pattern like '[%]'
Ищет процент персонажа. Полный список символов для побега -
'_', '%', '[', ']'
с соответствующими заменами'[_]', '[%]', '[[]', '[]]'
, Пример кода может быть найден в Escape Escape-символ не работает - SQL LIKE Operatorиспользуйте escape-символ, который вряд ли будет в строке, такой как обратный удар:
where pattern like '`%' escape '`'
(См. Синтаксис в MSDN - LIKE (Transact-SQL).)
В обоих случаях я бы предложил сделать подстановку на уровне приложения, но вы также можете сделать это в SQL, если вы действительно хотите:
where pattern like replace(@pattern, '%', '[%]')
И предоставление конечному пользователю доступа к групповым символам может быть хорошей вещью с точки зрения пользовательского интерфейса.
Примечание: есть еще пара специальных символов '-'
а также '^'
в запросе LIKE, но их не нужно экранировать, если вы уже экранировали '['
а также ']'
,
Вообще говоря, экранирование значений в SQL вручную считается плохой практикой, поскольку использование параметров является предпочтительным (и более безопасным) решением.
Однако в вашем примере вы уже используете параметры и хотите использовать оператор LIKE, поэтому экранирование символов в ручном режиме должно быть нормальным. Не забудьте также экранировать escape-символы - см. /questions/4680359/escaping-the-escape-character-does-not-work-sql-like-operator/4680369#4680369 для некоторого кода.
Вы можете сделать это следующим образом: указать явный escape-символ в строке SQL, а затем поместить этот escape перед всеми %
а также _
символы внутри строки, которые вводит пользователь:
SqlCommand findProcutsByPattern = new SqlCommand(
@"SELECT *
FROM [Products]
WHERE ProductName LIKE @pattern", connection) ESCAPE '_'"
Когда вы установите параметр, замените все экземпляры _
а также %
с __
а также _%
:
var escapedPattern = Regex.Replace(pattern, "[%_]", "_$0");
Demo.
Так что, в основном, я вручную экранировал (заменил) все символы подстановки, которые, кажется, теперь работают нормально. Вот окончательный код.
SqlCommand findProcutsByPattern = new SqlCommand(
"SELECT *" +
"FROM [Products]" +
"WHERE ProductName LIKE @pattern", connection);
string patternEscaped = pattern.Replace("_", "[_]");
patternEscaped = patternEscaped.Replace("%", "[%]");
patternEscaped = patternEscaped.Replace("[", "[[]");
findProcutsByPattern.Parameters.AddWithValue("@pattern", '%' + patternEscaped + '%');
Спасибо за поддержку!
ОБНОВЛЕНИЕ: я вижу...
escape_character Символ, который ставится перед подстановочным знаком, чтобы указать, что подстановочный знак следует интерпретировать как обычный символ, а не как подстановочный знак. escape_character - это символьное выражение, которое не имеет значения по умолчанию и должно содержать только один символ.
Так что вам все равно придется убежать самостоятельно.