_
a %
nejsou zástupné znaky v MySQL obecně a neměly by být zakódovány pro účely jejich vložení do normálních řetězcových literálů. mysql_real_escape_string
je pro tento účel správná a dostatečná. addcslashes
by se nemělo používat.
_
a %
jsou speciální pouze v kontextu LIKE
-vhodný. Když chcete připravit řetězce pro doslovné použití v LIKE
tak, že 100%
shoduje se se sto procenty a ne s ledajakým řetězcem začínajícím stovkou, máte dvě úrovně útěku, o které se můžete starat.
První je LIKE útěk. Zpracování LIKE probíhá výhradně uvnitř SQL, a pokud chcete změnit doslovný řetězec na doslovný výraz LIKE, musíte tento krok provést i když používáte parametrizované dotazy !
V tomto schématu _
a %
jsou speciální a je třeba uniknout. Únikový znak musí také uniknout. Podle ANSI SQL jiné znaky než tyto nesmí být escapován:\'
bylo by špatné. (I když MySQL vám to obvykle umožní.)
Když to uděláte, postoupíte do druhé úrovně escapování, což je prostý starý řetězcový doslovný escapování. To se děje mimo SQL a vytváří SQL, takže musí být provedeno po kroku Escape LIKE. Pro MySQL je to mysql_real_escape_string
jako dříve; pro jiné databáze bude funkce jiná, stačí použít parametrizované dotazy, abyste to nemuseli dělat.
Problém, který zde vede ke zmatku, je ten, že v MySQL používá zpětné lomítko jako únikový znak pro oba vnořené únikové kroky! Takže pokud byste chtěli porovnat řetězec s doslovným znakem procenta, museli byste dvojité zpětné lomítko-escape a říct LIKE 'something\\%'
. Nebo, pokud je to v PHP "
literál, který také používá escapování zpětného lomítka, "LIKE 'something\\\\%'"
. Argh!
Toto je nesprávné podle ANSI SQL, které říká, že:v řetězcových literálech zpětná lomítka znamenají doslovná zpětná lomítka a způsob, jak uniknout jediné uvozovce je ''
; ve výrazech LIKE ve výchozím nastavení není žádný znak escape.
Pokud tedy chcete LIKE-escape přenosným způsobem, měli byste přepsat výchozí (nesprávné) chování a zadat svůj vlastní escape znak pomocí LIKE ... ESCAPE ...
postavit. Pro zdravý rozum zvolíme něco jiného než to zatracené zpětné lomítko!
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 ...";
nebo s parametry (např. v PDO):
$q= $db->prepare("... WHERE name LIKE ? ESCAPE '=' AND ...");
$q->bindValue(1, '%'.like($name, '=').'%', PDO::PARAM_STR);
(Pokud chcete více přenosného času na párty, můžete se také pobavit pokusy o účet pro MS SQL Server a Sybase, kde [
znak je také nesprávně speciální v LIKE
prohlášení a musí uniknout. ano.)