如何在MySQL中转义特殊字符?


77

例如:

select * from tablename where fields like "%string "hi"  %";

错误:

您的SQL语法有误。检查与您的MySQL服务器版本相对应的手册,以在第1行的“ hi”“”附近使用正确的语法

如何建立此查询?


这可能会被骗到如何防止PHP中进行SQL注入?...(我并不是说这样做应该或正确—可能会发生。)
Peter Mortensen

Answers:


113

此答案中提供的信息可能会导致编程实践不安全。

此处提供的信息高度依赖于MySQL配置,包括(但不限于)程序版本,数据库客户端和使用的字符编码。

参见http://dev.mysql.com/doc/refman/5.0/en/string-literals.html

MySQL识别以下转义序列。
\ 0 ASCII NUL(0x00)字符。
\'单引号(“'”)字符。
\“双引号(”“”)字符。
\ b退格字符。
\ n换行符(换行符)。
\ r回车符。
\ t制表符。
\ Z ASCII 26(Control-Z)。请参阅表格后面的注释。
\\反斜杠(“ \”)字符。
\% 一个人物。请参阅表格后面的注释。
\_ 一个人物。请参阅表格后面的注释。

所以你需要

select * from tablename where fields like "%string \"hi\" %";

尽管正如Bill Karwin在下面指出的那样,对字符串定界符使用双引号不是标准的SQL,所以使用单引号是一个好习惯。这简化了事情:

select * from tablename where fields like '%string "hi" %';

3
为什么逃脱角色是不安全的?
彼得·莫滕森

@PeterMortensen因为您不能完全依靠它来清理不受信任的输入。这依赖于您转义服务器以不同的方式解释的所有内容,并且如备注所述,取决于所使用的配置,版本和编码。新版本可以轻松引入您没有考虑的新内容,或者您​​可能会轻易忘记一些角色,或者攻击者可以找到一些极端情况。最后,escapng使您摆脱了良好实践:对所有不受信任的参数使用参数,这些参数保证可以按数据库引擎的预期工作。
亚历杭德罗

35

我已经用Java开发了自己的MySQL转义方法(如果对任何人有用)。

请参阅下面的类代码。

警告:如果启用了NO_BACKSLASH_ESCAPES SQL模式,则错误。

private static final HashMap<String,String> sqlTokens;
private static Pattern sqlTokenPattern;

static
{           
    //MySQL escape sequences: http://dev.mysql.com/doc/refman/5.1/en/string-syntax.html
    String[][] search_regex_replacement = new String[][]
    {
                //search string     search regex        sql replacement regex
            {   "\u0000"    ,       "\\x00"     ,       "\\\\0"     },
            {   "'"         ,       "'"         ,       "\\\\'"     },
            {   "\""        ,       "\""        ,       "\\\\\""    },
            {   "\b"        ,       "\\x08"     ,       "\\\\b"     },
            {   "\n"        ,       "\\n"       ,       "\\\\n"     },
            {   "\r"        ,       "\\r"       ,       "\\\\r"     },
            {   "\t"        ,       "\\t"       ,       "\\\\t"     },
            {   "\u001A"    ,       "\\x1A"     ,       "\\\\Z"     },
            {   "\\"        ,       "\\\\"      ,       "\\\\\\\\"  }
    };

    sqlTokens = new HashMap<String,String>();
    String patternStr = "";
    for (String[] srr : search_regex_replacement)
    {
        sqlTokens.put(srr[0], srr[2]);
        patternStr += (patternStr.isEmpty() ? "" : "|") + srr[1];            
    }
    sqlTokenPattern = Pattern.compile('(' + patternStr + ')');
}


public static String escape(String s)
{
    Matcher matcher = sqlTokenPattern.matcher(s);
    StringBuffer sb = new StringBuffer();
    while(matcher.find())
    {
        matcher.appendReplacement(sb, sqlTokens.get(matcher.group(1)));
    }
    matcher.appendTail(sb);
    return sb.toString();
}

在mysql过程中使用了您的搜索替换表,在该过程中,我需要转义制表符分隔符,以便正确插入db'\ t'。thx
ErikČerpnjak'17

对我非常有用!问候!
保罗·巴尔加斯

您有C#版本吗?
阮阮

28

您应将单引号用于字符串定界符。单引号是标准的SQL字符串定界符,双引号是标识符定界符(因此,您可以在表或列的名称中使用特殊的单词或字符)。

在MySQL中,默认情况下,双引号(非标准地)用作字符串定界符(除非您设置了ANSISQL模式)。如果您使用其他品牌的SQL数据库,则养成按标准使用引号的习惯,将会从中受益。

使用单引号的另一个方便好处是,字符串中的文字双引号不需要转义:

select * from tablename where fields like '%string "hi" %';

我同意单引号的想法,因为如果您切换到PostgresSQL,它将固执地拒绝您的查询,并且您必须使用单引号。这是一个好习惯。
kovacsbv

可以处理示例,但是更一般的情况呢?例如反斜杠“ \”。
彼得·莫滕森

@PeterMortensen使用双反斜杠可获取一个文字反斜杠字符。几乎每种编程语言都一样。参见:dev.mysql.com/doc/refman/8.0/en/string-literals.html
比尔Karwin



8

对于这样的字符串,对我来说,最舒适的方法是将'或“加倍,如MySQL手册中所述:

有几种在字符串中包含引号字符的方法:

A “'” inside a string quoted with'” may be written as “''”.

A “"” inside a string quoted with “"” may be written as “""”.

Precede the quote character by an escape character (“\”).

A “'” inside a string quoted with"” needs no special treatment and need not be doubled or escaped. In the same way, “"” inside a

用“'”引号的字符串不需要特殊处理。

它来自http://dev.mysql.com/doc/refman/5.0/en/string-literals.html


1

为了测试如何使用终端在MySQL中插入双引号,可以使用以下方式:

TableName(Name,DString)->将模式
插入TableName值(“名称”,“我的QQDoubleQuotedStringQQ”)

插入值之后,可以用双引号或单引号更新数据库中的值:

update table TableName replace(Dstring, "QQ", "\"")

0

如果在搜索字符串时使用变量,mysql_real_escape_string()则对您有好处。只是我的建议:

$char = "and way's 'hihi'";
$myvar = mysql_real_escape_string($char);

select * from tablename where fields like "%string $myvar  %";

5
此功能在PHP 5.5中已弃用,并从7.0中删除
Phil M
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.