转义 MySQL 通配符

2022-08-30 12:12:50

在我使用的较旧的服务器上,我无法使用预准备语句,我目前正在尝试在将其发送到MySQL之前完全转义用户输入。为此,我正在使用PHP函数。mysql_real_escape_string

由于此函数不会转义MySQL通配符%和_,我也用它来转义这些通配符。addcslashes

当我发送类似的东西时:

test_test " ' 

到数据库,然后将其读回数据库显示:

test\_test " ' 

看着这个,我不明白为什么 _ 有前面的反斜杠,而 “ 和 ' 没有。由于它们都用\sure _ ' 和 “ 进行转义,因此它们看起来都相同,即所有转义字符都可见或全部不可见。

是否自动筛选出

谁能解释一下?


答案 1

_并且通常不是MySQL中的通配符,并且不应该为了将它们放入正常的字符串文本中而进行转义。 是正确且足以达到此目的。 不应使用。%mysql_real_escape_stringaddcslashes

_并且仅在 -match 的上下文中是特殊的。当您想要准备字符串以便在语句中使用文本时,以便百分之百匹配而不仅仅是以一百开头的任何字符串,您有两个级别的转义需要担心。%LIKELIKE100%

第一种是像逃避。LIKE处理完全在SQL内部进行,如果要将文本字符串转换为文本LIKE表达式,即使使用参数化查询,也必须执行此步骤!

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

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

这里导致混淆的问题是,在MySQL中,使用反斜杠作为两个嵌套转义步骤的转义字符!因此,如果您想将字符串与文字百分比符号进行匹配,则必须进行双反斜杠转义并说。或者,如果这是在也使用反斜杠转义的PHP文本中,则.唉!LIKE 'something\\%'""LIKE 'something\\\\%'"

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

因此,如果您想以可移植的方式进行 LIKE-escape,则应覆盖默认(错误)行为,并使用构造指定自己的转义字符。为了理智,我们将选择该死的反斜杠以外的其他东西!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


答案 2

令人惊讶的是,这么多年过去了,没有人愿意提到它,但是如果你不需要做复杂的通配符匹配(例如),我认为//,,,等应该就足够了。在我所有的情况下,我只在字符串中的任何地方进行匹配(例如),所以在所有关于逃避模式的恐怖故事之后,我现在使用的是。foo%bazINSTRLOCATEPOSITIONLEFTRIGHTLIKE%foobar%LIKEINSTR

等效项(在任何地方匹配):value LIKE '%foobar%'

INSTR(value, 'foobar') > 0

等效于(开始时匹配):value LIKE 'foobar%'

INSTR(value, 'foobar') = 1

等效(末尾匹配):value LIKE '%foobar'

RIGHT(value, 6) = 'foobar'

它可能不那么直截了当和容易记住,最后匹配的解决方案也许可以以某种方式改进,使其更加普遍。但是,这些替代方案至少应该在安全性方面让您高枕无忧,因为它绕过了任何自滚动转义的需要,并且不需要您更改实际的参数值(无论如何使用预准备语句时)。


推荐