Да, это настоящий беспорядок. И MySQL, и PostgreSQL используют для этого обратную косую черту по умолчанию. Это ужасная боль, если вы снова экранируете строку с помощью обратной косой черты вместо использования параметризации, и это также неверно в соответствии с ANSI SQL: 1992, который говорит, что по умолчанию нет никаких дополнительных escape-символов поверх обычного экранирования строки, и следовательно, нет способа включить литерал %
или _
.
Я бы предположил, что простой метод обратного слеша-замены также идет не так, если вы выключаете экранирование обратного слэша (которые сами не совместимы с ANSI SQL), используя NO_BACKSLASH_ESCAPE
sql_mode в MySQL или standard_conforming_strings
conf в PostgreSQL ( что разработчики PostgreSQL угрожали сделать для пары версий).
Единственным реальным решением является использование малоизвестного синтаксиса LIKE...ESCAPE
для указания явного escape-символа для LIKE
-шаблонов. Это используется вместо экранирования обратной косой черты в MySQL и PostgreSQL, заставляя их соответствовать тому, что делают все остальные, и предоставляя гарантированный способ включения внеполосных символов. Например, со знаком =
в качестве 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+'%'))
Это работает в PostgreSQL, MySQL и ANSI SQL-совместимых базах данных (конечно, по модулю paramstyle, который изменяется в разных модулях БД).
Возможно, все еще существует проблема с MS SQL Server / Sybase, который, по-видимому, также допускает использование групп символов [a-z]
в выражениях LIKE
. В этом случае вы также хотели бы экранировать буквальный символ [
с .replace('[', '=[')
. Однако в соответствии с ANSI SQL экранирование символа, который не нуждается в экранировании, недопустимо! (Argh!) Так что, хотя он, вероятно, все еще будет работать в реальных СУБД, вы все равно не будете соответствовать ANSI. Вздох ...