_
y %
no son comodines en MySQL en general, y no se deben escapar con el propósito de ponerlos en literales de cadena normales. mysql_real_escape_string
es correcto y suficiente para este propósito. addcslashes
no debe ser utilizado.
_
y %
son especiales únicamente en el contexto de LIKE
-emparejamiento. Cuando desee preparar cadenas para uso literal en una declaración LIKE
, para que 100%
coincida con el cien por ciento y no con cualquier cadena que comience con cien, tiene dos niveles de escape de los que preocuparse.
El primero es LIKE escaping. ¡El manejo de LIKE ocurre completamente dentro de SQL, y si desea convertir una cadena literal en una expresión LIKE literal, debe realizar este paso , incluso si está utilizando consultas parametrizadas!
En este esquema, _
y %
son especiales y se deben escapar. El personaje de escape también debe ser escapado. De acuerdo con ANSI SQL, los caracteres distintos de estos no deben escaparse: \'
sería incorrecto. (Aunque MySQL normalmente le permitirá salirse con la suya.)
Habiendo hecho esto, procederá al segundo nivel de escape, que es el antiguo escape literal de cadena antigua. Esto se lleva a cabo fuera de SQL, creando SQL, así que debe hacerse después del paso de escape LIKE. Para MySQL, esto es mysql_real_escape_string
como antes; para otras bases de datos habrá una función diferente, puede usar consultas parametrizadas para evitar tener que hacerlo.
¡El problema que lleva a confusión aquí es que en MySQL usa una barra invertida como un carácter de escape para los dos pasos de escape anidados! Entonces, si quisieras hacer coincidir una cuerda con un signo de porcentaje literal, tendrías que hacer una doble barra invertida: escapar y decir LIKE 'something\\%'
. O, si eso está en un literal PHP "
que también usa el escape de barra invertida, "LIKE 'something\\\\%'"
. Argh!
Esto es incorrecto de acuerdo con ANSI SQL, que dice que: en literals de cadena, las barras invertidas significan barras invertidas literales y la forma de escapar de una sola cita es ''
; en expresiones LIKE no hay ningún carácter de escape por defecto.
Así que si quiere LIKE-escapar de forma portátil, debe anular el comportamiento predeterminado (incorrecto) y especificar su propio carácter de escape, utilizando el constructo LIKE ... ESCAPE ...
. ¡Para la sensatez, elegiremos algo más que la maldita barra invertida!
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 ...";
o con parámetros (por ejemplo, en DOP.):
$q= $db->prepare("... WHERE name LIKE ? ESCAPE '=' AND ...");
$q->bindValue(1, '%'.like($name, '=').'%', PDO::PARAM_STR);
(Si quieres que el tiempo del partido más portabilidad, también puede divertirse tratando de dar cuenta de MS SQL Server y Sybase, donde el El carácter [
también es, incorrectamente, especial en una declaración LIKE
y tiene que ser escapado. Argh.)
¡Volvería a hacer +1 por "la maldita barra invertida!". – BoltClock
Gracias, acaba de absorber esto ahora ... esto realmente me está ayudando a ampliar mis conocimientos básicos. Estúpidamente, estaba escapando% y _ aunque en realidad no estoy usando ninguna declaración LIKE y como creo que (por favor confirma) que% y _ son solo comodines en el contexto de una declaración LIKE, de hecho estoy perdiendo el tiempo. Pero eso me hace pensar por qué querrías escapar de un% o _ cuando está en el contexto de una declaración LIKE. Seguramente la única razón para usar una declaración LIKE es para poder usar sus comodines. (Disculpe mi conocimiento limitado sobre esto) – Columbo
Claro, pero es perfectamente natural querer buscar un carácter literal '%' o '_'. Si un usuario busca '50%' en el front-end, probablemente signifiquen que están buscando una cadena que contenga '50%' y no cualquier cadena con '50' en ella. – bobince