_
et %
ne sont pas des caractères génériques dans MySQL en général et ne doivent pas être échappés dans le but de les mettre dans des littéraux de chaîne normaux. mysql_real_escape_string
est correct et suffisant à cette fin. addcslashes
ne doit pas être utilisé.
_
et %
sont spéciaux uniquement dans le contexte de LIKE
-correspondant à. Lorsque vous souhaitez préparer des chaînes pour une utilisation littérale dans un LIKE
déclaration, de sorte que 100%
correspond à cent pour cent et pas à n'importe quelle chaîne commençant par cent, vous devez vous soucier de deux niveaux d'échappement.
Le premier est COMME s'échapper. La gestion LIKE se déroule entièrement dans SQL, et si vous souhaitez transformer une chaîne littérale en une expression LIKE littérale, vous devez effectuer cette étape même si vous utilisez des requêtes paramétrées !
Dans ce schéma, _
et %
sont spéciaux et doivent être échappés. Le caractère d'échappement doit également être échappé. Selon ANSI SQL, les caractères autres que ceux-ci ne doivent pas être échappé :\'
serait faux. (Bien que MySQL vous laisse généralement vous en sortir.)
Après avoir fait cela, vous passez au deuxième niveau d'échappement, qui est l'échappement littéral de chaîne classique. Cela a lieu en dehors de SQL, créant SQL, donc doit être fait après l'étape d'échappement LIKE. Pour MySQL, c'est mysql_real_escape_string
comme avant; pour les autres bases de données, il y aura une fonction différente, vous pouvez simplement utiliser des requêtes paramétrées pour éviter d'avoir à le faire.
Le problème qui prête à confusion ici est que MySQL utilise une barre oblique inverse comme caractère d'échappement pour les deux étapes d'échappement imbriquées ! Donc, si vous vouliez faire correspondre une chaîne à un signe de pourcentage littéral, vous deviez doubler la barre oblique inverse et dire LIKE 'something\\%'
. Ou, si c'est dans un PHP "
littéral qui utilise également l'échappement par barre oblique inverse, "LIKE 'something\\\\%'"
. Argh !
Ceci est incorrect selon ANSI SQL, qui dit que :dans les littéraux de chaîne, les barres obliques inverses signifient des barres obliques inverses littérales et le moyen d'échapper à un guillemet simple est ''
; dans les expressions LIKE, il n'y a aucun caractère d'échappement par défaut.
Donc, si vous voulez utiliser LIKE-escape de manière portable, vous devez remplacer le comportement par défaut (incorrect) et spécifier votre propre caractère d'échappement, en utilisant le LIKE ... ESCAPE ...
construction. Pour être sain d'esprit, on choisira autre chose que ce satané antislash !
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 ...";
ou avec paramètres (ex. en PDO) :
$q= $db->prepare("... WHERE name LIKE ? ESCAPE '=' AND ...");
$q->bindValue(1, '%'.like($name, '=').'%', PDO::PARAM_STR);
(Si vous voulez plus de temps de fête sur la portabilité, vous pouvez également vous amuser à essayer de prendre en compte MS SQL Server et Sybase, où le [
le caractère est aussi, à tort, spécial dans un LIKE
déclaration et doit être échappé. argh.)