sql >> Base de Datos >  >> RDS >> PostgreSQL

Escape del valor SQL LIKE para Postgres con psycopg2

Sí, esto es un verdadero desastre. Tanto MySQL como PostgreSQL usan escapes de barra invertida para esto de forma predeterminada. Esto es un dolor terrible si también está escapando de la cadena nuevamente con barras diagonales inversas en lugar de usar la parametrización, y también es incorrecto de acuerdo con ANSI SQL:1992, que dice que, de forma predeterminada, no hay caracteres de escape adicionales además de la cadena de escape normal, y por lo tanto, no hay forma de incluir un % literal o _ .

Supongo que el método simple de reemplazo de barra invertida también falla si desactiva los escapes de barra invertida (que no cumplen con ANSI SQL), usando NO_BACKSLASH_ESCAPE sql_mode en MySQL o standard_conforming_strings conf en PostgreSQL (que los desarrolladores de PostgreSQL han estado amenazando con hacer durante un par de versiones).

La única solución real es usar el poco conocido LIKE...ESCAPE sintaxis para especificar un carácter de escape explícito para LIKE -patrón. Esto se usa en lugar del escape de barra invertida en MySQL y PostgreSQL, haciéndolos conformes con lo que hacen los demás y brindando una forma garantizada de incluir los caracteres fuera de banda. Por ejemplo con el = firmar como escape:

# 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+'%'))

Esto funciona en bases de datos compatibles con PostgreSQL, MySQL y ANSI SQL (módulo paramstyle, por supuesto, que cambia en diferentes módulos de base de datos).

Todavía puede haber un problema con MS SQL Server/Sybase, que aparentemente también permite [a-z] -grupos de caracteres de estilo en LIKE expresiones En este caso, querrá escapar también del literal [ carácter con .replace('[', '=[') . Sin embargo, de acuerdo con ANSI SQL, ¡escapar un carácter que no necesita escapar no es válido! (¡Argh!) Entonces, aunque probablemente seguirá funcionando en DBMS reales, aún no sería compatible con ANSI. suspiro...