Sì, questo è un vero casino. Sia MySQL che PostgreSQL utilizzano per impostazione predefinita i caratteri di escape barra rovesciata. Questo è un dolore terribile se si esegue nuovamente l'escape della stringa con barre inverse invece di utilizzare la parametrizzazione, ed è anche errato secondo ANSI SQL:1992, che afferma che per impostazione predefinita non ci sono caratteri di escape aggiuntivi oltre al normale escape di stringa e quindi non c'è modo di includere un letterale %
o _
.
Presumo che anche il semplice metodo backslash-replace vada storto se si disattivano i backslash-escape (che a loro volta non sono conformi ad ANSI SQL), usando NO_BACKSLASH_ESCAPE
sql_mode in MySQL o standard_conforming_strings
conf in PostgreSQL (cosa che gli sviluppatori di PostgreSQL hanno minacciato di fare per un paio di versioni ora).
L'unica vera soluzione è usare il poco conosciuto LIKE...ESCAPE
sintassi per specificare un carattere di escape esplicito per LIKE
-modello. Questo viene utilizzato al posto dell'escape della barra rovesciata in MySQL e PostgreSQL, rendendoli conformi a ciò che fanno tutti gli altri e fornendo un modo garantito per includere i caratteri fuori banda. Ad esempio con il =
firmare come via di fuga:
# look for term anywhere within title
term= term.replace('=', '==').replace('%', '=%').replace('_', '=_')
sql= "SELECT * FROM things WHERE description LIKE %(like)s ESCAPE '='"
cursor.execute(sql, dict(like= '%'+term+'%'))
Funziona su database compatibili con PostgreSQL, MySQL e ANSI SQL (modulo the paramstyle ovviamente che cambia su diversi moduli db).
Potrebbe esserci ancora un problema con MS SQL Server/Sybase, che apparentemente consente anche [a-z]
-style gruppi di caratteri in LIKE
espressioni. In questo caso vorresti anche sfuggire al letterale [
carattere con .replace('[', '=[')
. Tuttavia, secondo ANSI SQL l'escape di un carattere che non necessita di escape non è valido! (Argh!) Quindi, anche se probabilmente funzionerà ancora su DBMS reali, non saresti comunque conforme ad ANSI. sospiro...