PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Esci dal valore SQL LIKE per Postgres con psycopg2

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