_
i %
nie są symbolami wieloznacznymi w MySQL w ogóle i nie powinny być zmieniane w celu umieszczenia ich w normalnych literałach łańcuchowych. mysql_real_escape_string
jest poprawne i wystarczające do tego celu. addcslashes
nie powinno być używane.
_
i %
są wyjątkowe wyłącznie w kontekście LIKE
-dopasowanie. Gdy chcesz przygotować ciągi do dosłownego użycia w LIKE
oświadczenie, aby 100%
pasuje do stu procent, a nie do dowolnego ciągu zaczynającego się od stu, masz dwa poziomy ucieczki, o które musisz się martwić.
Pierwszy to LIKE ucieczka. Obsługa LIKE odbywa się całkowicie wewnątrz SQL, a jeśli chcesz zamienić literał ciągu w dosłowne wyrażenie LIKE, musisz wykonać ten krok nawet jeśli używasz zapytań parametrycznych !
W tym schemacie _
i %
są wyjątkowe i należy im uciec. Znak ucieczki również musi zostać zmieniony. Według ANSI SQL znaki inne niż te nie mogą być zmienionym:\'
byłoby źle. (Chociaż MySQL zazwyczaj pozwala ci ujść na sucho.)
Po wykonaniu tej czynności przechodzisz do drugiego poziomu ucieczki, który jest zwykłym, starym, starym ucieknięciem literału łańcuchowego. Odbywa się to poza SQL, tworząc SQL, więc należy to zrobić po kroku ucieczki LIKE. W przypadku MySQL jest to mysql_real_escape_string
jak wcześniej; dla innych baz danych będzie inna funkcja, możesz po prostu użyć sparametryzowanych zapytań, aby uniknąć konieczności robienia tego.
Problem, który prowadzi do zamieszania, polega na tym, że w MySQL używa się odwrotnego ukośnika jako znaku ucieczki dla obu zagnieżdżonych kroków ucieczki! Więc jeśli chcesz dopasować ciąg znaków do dosłownego znaku procentu, musiałbyś użyć podwójnego ukośnika odwrotnego i powiedzieć LIKE 'something\\%'
. Lub, jeśli to jest w PHP "
literał, który również używa ucieczki odwrotnym ukośnikiem, "LIKE 'something\\\\%'"
. Ach!
Jest to niepoprawne według ANSI SQL, który mówi, że:w literałach łańcuchowych ukośniki odwrotne oznaczają dosłowne ukośniki odwrotne, a sposobem na uniknięcie pojedynczego cudzysłowu jest ''
; w wyrażeniach LIKE domyślnie nie ma żadnego znaku ucieczki.
Więc jeśli chcesz wykonać LIKE-escape w przenośny sposób, powinieneś zastąpić domyślne (złe) zachowanie i określić własny znak ucieczki, używając LIKE ... ESCAPE ...
zbudować. Dla zdrowia psychicznego wybierzemy coś innego niż cholerny ukośnik odwrotny!
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 ...";
lub z parametrami (np. w PDO):
$q= $db->prepare("... WHERE name LIKE ? ESCAPE '=' AND ...");
$q->bindValue(1, '%'.like($name, '=').'%', PDO::PARAM_STR);
(Jeśli chcesz mieć więcej czasu na przenośność, możesz również dobrze się bawić, próbując uwzględnić MS SQL Server i Sybase, gdzie [
znak jest również, niepoprawnie, specjalny w LIKE
oświadczenie i należy uciec. argh.)