Экранирование специальных символов в операторе 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 - это символьное выражение, которое не имеет значения по умолчанию и должно содержать только один символ.

Так что вам все равно придется убежать самостоятельно.

Другие вопросы по тегам