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