_
и %
вообще не являются подстановочными знаками в MySQL и не должны быть экранированы для целей помещения их в обычные строковые литералы.mysql_real_escape_string
правильно и достаточно для этой цели.addcslashes
не следует использовать.
_
и %
являются специальными исключительно в контексте LIKE
-спарения.Если вы хотите подготовить строки для буквального использования в операторе LIKE
, чтобы 100%
соответствовал сто процентам, а не просто любой строке, начинающейся со сотни, у вас есть два уровня экранирования, о которых нужно беспокоиться.
Первое, КАК сбежать.Обработка LIKE происходит полностью внутри SQL, и если вы хотите превратить буквальную строку в литеральное выражение LIKE, вы должны выполнить этот шаг , даже если вы используете параметризованные запросы !
В этой схеме, _
и %
являются специальными и должны быть экранированы.Экранирующий персонаж также должен быть экранирован.В соответствии с ANSI SQL символы, отличные от , не должны экранироваться : \'
будет неправильным.(Хотя MySQL обычно позволяет вам избежать неприятностей.)
Сделав это, вы переходите ко второму уровню экранирования, который является простым экранированием старых строковых литералов.Это происходит за пределами SQL, создавая SQL, поэтому это должно быть сделано после шага экранирования LIKE.Для MySQL это mysql_real_escape_string
как и раньше;для других баз данных будет другая функция, вы можете просто использовать параметризованные запросы, чтобы избежать необходимости делать это.
Проблема, которая приводит к путанице, заключается в том, что в MySQL используется обратный слеш в качестве escape-символа для обоихвложенных спасательных шагов!Так что, если вы хотите сопоставить строку с буквенным знаком процента, вам придется дважды нажать обратную косую черту и сказать LIKE 'something\\%'
.Или, если это в литерале PHP "
, который также использует экранирование обратной косой черты, "LIKE 'something\\\\%'"
.Argh!
Это неверно в соответствии с ANSI SQL, который гласит: в строковых литералах обратные косые черты означают литеральные обратные косые черты и способ избежать одиночной кавычки - ''
;в выражениях LIKE по умолчанию вообще нет escape-символа.
Поэтому, если вы хотите LIKE-escape переносимым способом, вам следует переопределить поведение по умолчанию (неправильное) и указать свой собственный 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
и должен быть экранирован. argh.)