为了账号安全,请及时绑定邮箱和手机立即绑定

转义MySQL通配符

转义MySQL通配符

红糖糍粑 2019-10-17 15:45:10
在较旧的服务器上,我无法使用准备好的语句,因为我目前正试图在将用户输入发送到MySQL之前完全转义用户输入。为此,我正在使用PHP函数mysql_real_escape_string。由于此函数无法转义MySQL通配符%和_,因此我也正addcslashes对这些通配符进行转义。当我发送类似:test_test " ' 到数据库,然后再读回数据库,显示:test\_test " ' 看着这个我不明白为什么_前面有一个反斜杠,但是“和'却没有。因为它们都用\进行了转义,因此_'和”应该都看起来一样,即所有的转义字符都可见或所有的东西都不可见。是否自动筛选了转义的\谁能解释一下?
查看完整描述

2 回答

?
动漫人物

TA贡献1815条经验 获得超10个赞

_而%不是通配符在MySQL一般,而且不应该被转义,将它们放入普通的字符串字面量的目的。mysql_real_escape_string是正确的,足以满足此目的。addcslashes不应该使用。


_并且%仅在LIKE-matching 上下文中是特殊的。当您想为LIKE语句中的文字使用准备字符串时,要100%匹配百分之一百,而不仅仅是以100开头的任何字符串,都需要担心两种转义。


首先是喜欢转义。LIKE处理完全在SQL内部进行,如果要将文字字符串转换为文字LIKE表达式,即使使用参数化查询,也必须执行此步骤!


在此方案中,_并且%是特殊的,必须进行转义。转义字符也必须转义。根据ANSI SQL,除这些字符外,不得转义:\'这是错误的。(尽管MySQL通常会让您摆脱它。)


完成此操作后,您进入第二个转义级别,这是普通的旧字符串文字转义。这发生在SQL之外,创建SQL,因此必须在LIKE转义步骤之后完成。对于MySQL,这mysql_real_escape_string和以前一样。对于其他数据库,它将具有不同的功能,您可以只使用参数化查询来避免这样做。


这里引起混乱的问题是,在MySQL中,两个嵌套转义步骤都使用反斜杠作为转义字符!因此,如果要将字符串与文字百分号匹配,则必须双反斜杠转义并说出LIKE 'something\\%'。或者,如果在PHP "文字中也使用反斜杠转义,则"LIKE 'something\\\\%'"。啊!


根据ANSI SQL,这是不正确的,它表示:在字符串文字中,反斜杠表示文字反斜杠,而转义单引号的方式为'';在LIKE表达式中,默认情况下根本没有转义符。


因此,如果要以可移植的方式进行LIKE逸出,则应覆盖默认(错误)行为,并使用该LIKE ... ESCAPE ...构造指定自己的逸出字符。为了理智,我们将选择除该死的反斜杠以外的其他东西!


function like($s, $e) {

    return str_replace(array($e, '_', '%'), array($e.$e, $e.'_', $e.'%'), $s);

}


$escapedname= mysql_real_escape_string(like($name, '='));

$query= "... WHERE name LIKE '%$escapedname%' ESCAPE '=' AND ...";

或带有参数(例如在PDO中):


$q= $db->prepare("... WHERE name LIKE ? ESCAPE '=' AND ...");

$q->bindValue(1, '%'.like($name, '=').'%', PDO::PARAM_STR);

(如果您希望有更多的可移植性聚会时间,那么尝试考虑MS SQL Server和Sybase也可能会很有趣,因为在[错误的情况下,该字符在LIKE语句中也很特殊,必须转义。argh。)


查看完整回答
反对 回复 2019-10-17
?
三国纷争

TA贡献1804条经验 获得超7个赞

现在就开始吸收...这确实有助于我扩展基础知识。愚蠢的是,尽管我实际上并未使用任何LIKE语句,但我仍在转义%和_,并且由于我认为(请确认)%和_仅在LIKE语句的上下文中是百搭的,所以我实际上是在浪费时间。但是,那让我想起为什么在LIKE语句的上下文中,为什么要转义%或_。当然,使用LIKE语句的唯一原因是可以使用它的通配符。(请原谅我对此的有限知识)

查看完整回答
反对 回复 2019-10-17
  • 2 回答
  • 0 关注
  • 560 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信