Mysql
 sql >> Database >  >> RDS >> Mysql

Fuga dai caratteri jolly di MySQL

_ e % non sono caratteri jolly in MySQL in generale e non devono essere sottoposti a escape allo scopo di inserirli in normali stringhe letterali. mysql_real_escape_string è corretto e sufficiente per questo scopo. addcslashes non deve essere utilizzato.

_ e % sono speciali esclusivamente nel contesto di LIKE -corrispondenza. Quando vuoi preparare le stringhe per l'uso letterale in un LIKE dichiarazione, in modo che 100% corrisponde al cento per cento e non a qualsiasi stringa che inizia con cento, hai due livelli di evasione di cui preoccuparti.

Il primo è COME scappare. La gestione di LIKE avviene interamente all'interno di SQL e se si desidera trasformare una stringa letterale in un'espressione LIKE letterale è necessario eseguire questo passaggio anche se si utilizzano query parametrizzate !

In questo schema, _ e % sono speciali e devono essere evasi. Anche il carattere di escape deve essere sottoposto a escape. Secondo ANSI SQL, caratteri diversi da questi non devono essere sottoposto a escape:\' sarebbe sbagliato. (Anche se MySQL in genere ti consente di farla franca.)

Fatto ciò, si passa al secondo livello di escape, che è un semplice escape letterale di una vecchia stringa. Ciò avviene al di fuori di SQL, creando SQL, quindi deve essere eseguito dopo il passaggio LIKE di escape. Per MySQL, questo è mysql_real_escape_string come prima; per altri database ci sarà una funzione diversa, di cui puoi semplicemente usare query parametrizzate per evitare di doverlo fare.

Il problema che crea confusione qui è che in MySQL usa una barra rovesciata come carattere di escape per entrambi i passaggi di escape annidati! Quindi, se si desidera confrontare una stringa con un segno di percentuale letterale, è necessario eseguire il double-backslash-escape e dire LIKE 'something\\%' . Oppure, se è in un " PHP letterale che usa anche l'escape della barra rovesciata, "LIKE 'something\\\\%'" . Argh!

Questo non è corretto secondo ANSI SQL, che dice che:nei valori letterali di stringa le barre inverse significano le barre inverse letterali e il modo per sfuggire a una virgoletta singola è ''; nelle espressioni LIKE non è presente alcun carattere di escape per impostazione predefinita.

Quindi, se vuoi fare LIKE-escape in modo portatile, dovresti ignorare il comportamento predefinito (sbagliato) e specificare il tuo carattere di escape, usando LIKE ... ESCAPE ... costruire. Per sanità mentale, sceglieremo qualcosa di diverso dalla dannata barra rovesciata!

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 parametri (es. in PDO):

$q= $db->prepare("... WHERE name LIKE ? ESCAPE '=' AND ...");
$q->bindValue(1, '%'.like($name, '=').'%', PDO::PARAM_STR);

(Se vuoi più tempo di festa della portabilità, puoi anche divertirti provando a tenere conto di MS SQL Server e Sybase, dove il [ il carattere è anche, erroneamente, speciale in un LIKE dichiarazione e deve essere evitato. arg.)