2010-09-10 15 views
35

Su un server precedente sto usando che non posso usare le istruzioni preparate sto cercando di scappare completamente dall'input dell'utente prima di inviarlo a MySQL. Per questo sto usando la funzione PHP mysql_real_escape_string.Scappare le wild card MySQL

Poiché questa funzione non sfugge ai caratteri jolly MySQL% e _ Sto utilizzando addcslashes per evitare anche questi.

Quando trasmetto qualcosa di simile:

test_test " ' 

al database e poi leggere di nuovo il database mostra:

test\_test " ' 

Guardando a questo non riesco a capire il motivo per cui il _ ha un precedente backslash ma il "e" no. Poiché sono tutti sfuggiti con \ sicuramente _ "e" dovrebbero apparire tutti uguali, cioè tutti hanno il carattere di escape visibile o tutti non lo hanno visibile.

sono gli escape \ S proiettato automaticamente fuori per

Qualcuno può spiegare questo?

risposta

79

_ 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.)

+4

Vorrei fare ancora +1 per "il dannato backslash!". – BoltClock

+0

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

+2

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