Escaping special characters in a SQL LIKE statement using sql parameters

20,844

Solution 1

You have two options:

  • enclose them in [ and ]. So:

    where pattern like '[%]'
    

    Looks for the percentage character. Full list of characters to escape - '_', '%', '[', ']' with corresponding replacements '[_]', '[%]', '[[]', '[]]'. Sample code can be found in Escaping the escape character does not work – SQL LIKE Operator

  • use an escape character that is unlikely to be in the string, such as a backtick:

    where pattern like '`%' escape '`'
    

    (See the syntax on MSDN - LIKE (Transact-SQL).)

In both cases, I would suggest that you make the substitution in the application layer, but you can also do it in SQL if you really want:

where pattern like replace(@pattern, '%', '[%]')

And, giving the end-user access to wildcards may be a good thing in terms of the user interface.


Note: there are couple more special characters '-' and '^' in the LIKE query, but they don't need to be escaped if you are already escaping '[' and ']'.

Solution 2

You can do it like this: specify an explicit escape character in your SQL string, and then place that escape in front of all % and _ characters inside the string the user enters:

SqlCommand findProcutsByPattern = new SqlCommand(
    @"SELECT *
    FROM [Products]
    WHERE ProductName LIKE @pattern", connection) ESCAPE '_'"

When you set the parameter, replace all instances of _ and % with __ and _%:

var escapedPattern = Regex.Replace(pattern, "[%_]", "_$0");

Demo.

Solution 3

Generally speaking, manually escaping values in SQL is considered bad practice as using parameters is the preferred (and more secure) solution.

In your example, however, you are already using parameters and you want to use the LIKE operator, so manually escaping the characters should be fine. Don't forget escaping the escape characters, too - see https://stackoverflow.com/a/13861567/232175 for some code.

Solution 4

So, basically, I manually escaped(replaced) all the wildcard symbols, which seems to work fine now. Here is the final code.

        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 + '%');

Thank you for the support!

UPDATE: I see...

escape_character Is a character that is put in front of a wildcard character to indicate that the wildcard should be interpreted as a regular character and not as a wildcard. escape_character is a character expression that has no default and must evaluate to only one character.

So you still have to do the escaping yourself.

Share:
20,844
zhulien
Author by

zhulien

Updated on August 21, 2021

Comments

  • zhulien
    zhulien over 2 years

    I have a table containing products. I need to make a query finding all the matching results to an user-input value. I am using SqlParameter for the insertion of the inputs.

    SqlCommand findProcutsByPattern = new SqlCommand(
        "SELECT *" +
        " FROM [Products]" +
        " WHERE ProductName LIKE @pattern", connection);
    
    findProcutsByPattern.Parameters.AddWithValue("@pattern", '%' + pattern + '%');
    

    The problem comes when the user input string contains '_' or '%' as they're being interpreted as special characters. In the other hand, considering this:

    Command objects use parameters to pass values to SQL statements or stored procedures, providing type checking and validation. Unlike command text, parameter input is treated as a literal value, not as executable code.

    I shouldn't have such problems. Do I need to replace/escape all the '_' and '%' in the input string or is there a more elegant solution. I want the input to be considered as a literal.

    I have a few records in the table which include special characters in the name(N_EW, N\EW, N%EW, N"EW, N'EW). Specifying \, ", and ' as the input works fine(considers them as literals).