2014-09-06 42 views
2

我有一个包含产品的表。我需要查询所有匹配结果以查找用户输入值。我正在使用SqlParameter来插入输入。使用sql参数在SQL LIKE语句中转义特殊字符

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

findProcutsByPattern.Parameters.AddWithValue("@pattern", '%' + pattern + '%'); 

问题出现在用户输入字符串包含'_'或'%'时,因为它们被解释为特殊字符。在另一方面,考虑到这一点:

Command对象使用参数值传递给SQL语句或 存储过程,提供类型检查和验证。与 命令文本不同,参数输入被视为文字值,而不是 可执行代码。

我不应该有这样的问题。我是否需要替换/转义输入字符串中的所有'_'和'%',还是有更优雅的解决方案。我希望输入被视为文字。

我在表中的记录数,其中包括特殊字符的名称(N_EW,N \ EW,N EW%,N “EW,N'EW)指定\,并'作为输入工作正常(认为他们是文字)。

+0

您的查询连接到'SELECT * FROM [Products] WHERE ProductName LIKE @ pattern'您错过了一些空格 – 2014-09-06 18:55:04

+0

不用担心空格,查询工作得很好。除了特殊字符的东西..:) – zhulien 2014-09-06 19:06:03

+0

这个特定的查询确实有效。但是如果用列名替换'*',那么它就不会。但这只是未来查询的暗示 – 2014-09-06 20:05:03

回答

5

你有两个选择:

  • 将它们用[]。所以:

    where pattern like '[%]' 
    

    寻找百分比字符。 完整的字符列表逃脱 - '_', '%', '[', ']'与相应的替换'[_]', '[%]', '[[]', '[]]'。示例代码可以在Escaping the escape character does not work – SQL LIKE Operator

  • 使用中找到一个转义字符是不太可能的字符串,如反引号:(参见MSDN上的语法 - LIKE (Transact-SQL)

    where pattern like '`%' escape '`' 
    

在这两种情况下,我建议您在应用层的替代,但你也可以做到这一点的SQL如果你真的想:

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

而且,就用户界面而言,让最终用户访问通配符可能是件好事。


注:有几个比较特殊字符'-'并在LIKE查询'^',但他们并不需要,如果你已经逃离'['']'进行转义。

1

一般来说,手动转义SQL中的值被认为是不好的做法,因为使用参数是首选(也是更安全)的解决方案。

然而在你的例子中,你已经在使用参数,并且你想使用LIKE操作符,所以手动转义字符应该没问题。不要忘记逃避转义字符 - 有关某些代码,请参见https://stackoverflow.com/a/13861567/232175

1

你可以这样说:指定你的SQL字符串明确的转义字符,然后将所逃脱的所有%_字符前面的字符串中的用户输入:

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

当你设置参数,用___%取代_%所有实例:

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

Demo.

0

所以,基本上,我手动转义(替换)所有的通配符符号,现在看起来工作正常。这是最终的代码。

 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是一个 字符表达式,它没有默认值,只能计算一个 字符。

所以你仍然必须逃避自己。

+0

上面的代码无法完美工作,因为它会首先将“%”替换为“[%]”,然后它将用[[]替换,导致字符串“[[]%]”)。 如果您更改.Replace呼叫的顺序,先放置[置换,它会更好。 – 2016-08-24 13:59:03