_
e %
non sono caratteri jolly in MySQL in generale e non devono essere sfuggiti allo scopo di inserirli in stringhe letterali normali. mysql_real_escape_string
è corretto e sufficiente per questo scopo. addcslashes
non dovrebbe essere usato.
_
e %
sono speciali solo nel contesto di LIKE
-matching. Quando si desidera preparare stringhe per l'uso letterale in una dichiarazione LIKE
, in modo che 100%
corrisponda al cento percento e non a qualsiasi stringa che inizia con un centinaio, si hanno due livelli di escape di cui preoccuparsi.
Il primo è COME scappare. La gestione 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 parametrate!
In questo schema, _
e %
sono speciali e devono essere sottoposti a escaping. Anche il carattere di escape deve essere scappato. Secondo ANSI SQL, i caratteri diversi da questi non devono essere sfuggiti a: \'
sarebbe sbagliato. (Anche se MySQL in genere ti consente di farla franca.)
Fatto ciò, si procede al secondo livello di escape, che è una semplice stringa di escape letterale. Questo avviene al di fuori di SQL, creando SQL, quindi deve essere fatto dopo il passaggio di escape LIKE. Per MySQL, questo è mysql_real_escape_string
come prima; per gli altri database ci sarà una funzione diversa, basta usare le query parametrizzate per evitare di doverlo fare.
Il problema che porta alla confusione qui è che in MySQL utilizza un backslash come carattere di escape per entrambi i passaggi di escape annidati! Pertanto, se si desidera associare una stringa a un segno di percentuale letterale, è necessario eseguire il double-backslash-escape e pronunciare LIKE 'something\\%'
. Oppure, se questo è in un valore letterale PHP "
che utilizza anche l'escape alla barra rovesciata, "LIKE 'something\\\\%'"
. Argh!
Questo non è corretto secondo ANSI SQL, che dice che: in stringhe letterali i backslash significano letterali backslash e il modo per sfuggire a una virgoletta singola è ''
; nelle espressioni LIKE non esiste alcun carattere di escape per impostazione predefinita.
Quindi, se si desidera eseguire l'escape LIKE in modo portatile, è necessario ignorare il comportamento predefinito (errato) e specificare il proprio carattere di escape, utilizzando il costrutto LIKE ... ESCAPE ...
. Per sanità mentale, sceglieremo qualcosa di diverso da quella 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 di parametri (ad esempio in PDO.):
$q= $db->prepare("... WHERE name LIKE ? ESCAPE '=' AND ...");
$q->bindValue(1, '%'.like($name, '=').'%', PDO::PARAM_STR);
(Se si vuole tempo partito più portabilità, è anche possibile divertirsi cercando di tenere conto di MS SQL Server e Sybase, dove la Il carattere [
è anche, in modo errato, speciale in una dichiarazione LIKE
e deve essere preceduto da escape. Argh.)
Vorrei fare ancora +1 per "il dannato backslash!". – BoltClock
Grazie, ora sto assorbendo questo ... questo mi sta aiutando ad espandere le mie conoscenze di base. Stupidamente, stavo sfuggendo a% e _ anche se in realtà non sto usando nessuna istruzione LIKE e poiché penso (per favore conferma) che% e _ sono selvaggi solo nel contesto di una dichiarazione LIKE, sto in effetti sprecando il mio tempo. Ma poi questo mi fa pensare perché vorresti mai sfuggire a% o _ quando è nel contesto di una dichiarazione LIKE. Sicuramente l'unica ragione per usare un'istruzione LIKE è così che puoi usare i suoi caratteri jolly. (per favore scusami le mie conoscenze limitate su questo) – Columbo
Certo, ma è perfettamente naturale voler essere in grado di cercare un carattere letterale '%' o '_'. Se un utente cerca "50%" nel front-end, probabilmente significa che sta cercando una stringa contenente "50%" e non solo una stringa con "50" in essa. – bobince