PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Escape do valor SQL LIKE para Postgres com psycopg2


Sim, isso é uma verdadeira bagunça. Tanto o MySQL quanto o PostgreSQL usam escapes de barra invertida para isso por padrão. Isso é uma dor terrível se você também estiver escapando a string novamente com barras invertidas em vez de usar parametrização, e também está incorreto de acordo com ANSI SQL:1992, que diz que, por padrão, não há caracteres de escape extras em cima do escape normal de string e portanto, não há como incluir um literal % ou _ .

Eu presumo que o método simples de substituição de barra invertida também dê errado se você desativar os escapes de barra invertida (que não são compatíveis com ANSI SQL), usando NO_BACKSLASH_ESCAPE sql_mode no MySQL ou standard_conforming_strings conf no PostgreSQL (o que os desenvolvedores do PostgreSQL vêm ameaçando fazer há algumas versões).

A única solução real é usar o pouco conhecido LIKE...ESCAPE sintaxe para especificar um caractere de escape explícito para o LIKE -padronizar. Isso é usado em vez do escape de barra invertida no MySQL e no PostgreSQL, tornando-os conforme o que todos os outros fazem e dando uma maneira garantida de incluir os caracteres fora de banda. Por exemplo, com o = sinal como uma 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+'%'))

Isso funciona em bancos de dados compatíveis com PostgreSQL, MySQL e ANSI SQL (módulo o paramstyle, é claro, que muda em diferentes módulos db).

Ainda pode haver um problema com o MS SQL Server/Sybase, que aparentemente também permite [a-z] -style grupos de caracteres em LIKE expressões. Nesse caso, você também deseja escapar do literal [ caractere com .replace('[', '=[') . No entanto, de acordo com o ANSI SQL, o escape de um caractere que não precisa de escape é inválido! (Argh!) Portanto, embora provavelmente ainda funcione em DBMSs reais, você ainda não seria compatível com ANSI. suspirar...