Solución:
_
y %
no son comodines en MySQL en general, y no deben escaparse con el propósito de ponerlos en cadenas literales normales. mysql_real_escape_string
es correcto y suficiente para este propósito. addcslashes
No debería ser usado.
_
y %
son especiales únicamente en el contexto de LIKE
-pareo. Cuando desee preparar cadenas para uso literal en una LIKE
declaración, para que 100%
coincide con el cien por cien y no con cualquier cadena que comience con cien, tienes dos niveles de escape de los que preocuparte.
El primero es como escapar. El manejo de LIKE se lleva a cabo 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 hay que escapar. El carácter de escape también debe escaparse. Según ANSI SQL, caracteres distintos a estos no debe ser escapado: '
estaría mal. (Aunque MySQL normalmente le permitirá salirse con la suya).
Una vez hecho esto, pasa al segundo nivel de escape, que es un simple escape literal de cadena antigua. Esto tiene lugar fuera de SQL, creando SQL, por lo que debe realizarse 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, de usted puede usar consultas parametrizadas para evitar tener que hacerlo.
El problema que genera confusión aquí es que en MySQL se usa una barra invertida como carácter de escape para los dos pasos de escape anidados. Entonces, si quisieras hacer coincidir una cadena con un signo de porcentaje literal, tendrías que hacer doble barra invertida-escapar y decir LIKE 'something\%'
. O, si está en PHP "
literal que también usa el escape de barra invertida, "LIKE 'something\\%'"
. ¡Argh!
Esto es incorrecto según ANSI SQL, que dice que: en los literales de cadena, las barras invertidas significan barras invertidas literales y la forma de escapar de una comilla simple es ''
; en las expresiones LIKE no hay ningún carácter de escape por defecto.
Entonces, si desea hacer LIKE-escape de una manera portátil, debe anular el comportamiento predeterminado (incorrecto) y especificar su propio carácter de escape, utilizando el LIKE ... ESCAPE ...
construir. ¡Para la cordura, 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 (p. ej. en PDO):
$q= $db->prepare("... WHERE name LIKE ? ESCAPE '=' AND ...");
$q->bindValue(1, '%'.like($name, '=').'%', PDO::PARAM_STR);
(Si desea más tiempo de fiesta de portabilidad, también puede divertirse tratando de dar cuenta de MS SQL Server y Sybase, donde el [
carácter también es, incorrectamente, especial en un LIKE
declaración y tiene que ser escapado. argh.)