_
e %
não são curingas no MySQL em geral e não devem ser escapados para fins de colocá-los em literais de string normais. mysql_real_escape_string
é correto e suficiente para este fim. addcslashes
não deve ser usado. _
e %
são especiais apenas no contexto de LIKE
-Coincidindo. Quando você deseja preparar strings para uso literal em um LIKE
declaração, para que 100%
corresponde a cem por cento e não apenas qualquer string começando com cem, você tem dois níveis de escape para se preocupar. O primeiro é como escapar. O tratamento LIKE ocorre inteiramente dentro do SQL, e se você quiser transformar uma string literal em uma expressão LIKE literal, você deve executar esta etapa mesmo se estiver usando consultas parametrizadas !
Neste esquema,
_
e %
são especiais e devem ser evitados. O caractere de escape também deve ser escapado. De acordo com o ANSI SQL, caracteres diferentes desses não devem ser escapado:\'
estaria errado. (Embora o MySQL normalmente deixe você se safar.) Tendo feito isso, você prossegue para o segundo nível de escape, que é o escape literal de cadeia de caracteres simples. Isso ocorre fora do SQL, criando o SQL, portanto, deve ser feito após a etapa de escape LIKE. Para MySQL, este é
mysql_real_escape_string
como antes; para outros bancos de dados haverá uma função diferente, você pode apenas usar consultas parametrizadas para evitar ter que fazer isso. O problema que leva à confusão aqui é que no MySQL usa uma barra invertida como um caractere de escape para ambas as etapas de escape aninhadas! Portanto, se você quisesse corresponder uma string a um sinal de porcentagem literal, teria que usar a barra invertida e escapar e dizer
LIKE 'something\\%'
. Ou, se estiver em um PHP "
literal que também usa escape de barra invertida, "LIKE 'something\\\\%'"
. Argh! Isso está incorreto de acordo com o ANSI SQL, que diz que:em literais de string, barras invertidas significam barras invertidas literais e a maneira de escapar de uma aspa simples é
''
; em expressões LIKE não há nenhum caractere de escape por padrão. Portanto, se você deseja LIKE-escape de maneira portátil, deve substituir o comportamento padrão (errado) e especificar seu próprio caractere de escape, usando o
LIKE ... ESCAPE ...
construir. Por sanidade, escolheremos algo diferente da 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 ...";
ou com parâmetros (por exemplo, em PDO):
$q= $db->prepare("... WHERE name LIKE ? ESCAPE '=' AND ...");
$q->bindValue(1, '%'.like($name, '=').'%', PDO::PARAM_STR);
(Se você quiser mais tempo de festa de portabilidade, você também pode se divertir tentando contabilizar o MS SQL Server e Sybase, onde o
[
caractere também é, incorretamente, especial em um LIKE
declaração e tem que ser escapado. argh.)