_ 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.)