Tak, to jest prawdziwy bałagan. Zarówno MySQL, jak i PostgreSQL domyślnie używają w tym celu backslash-escapes. Jest to straszny problem, jeśli ponownie unikasz ciągu za pomocą ukośników odwrotnych zamiast używać parametryzacji, a także jest to niepoprawne zgodnie z ANSI SQL:1992, które mówi, że domyślnie nie ma żadnych dodatkowych znaków ucieczki poza normalnym ciągiem ucieczki, i stąd nie ma możliwości włączenia dosłownego %
lub _
.
Przypuszczam, że prosta metoda zastępowania ukośnika odwrotnego również działa źle, jeśli wyłączysz znaki ucieczki odwrotnego ukośnika (które same w sobie nie są zgodne z ANSI SQL), używając NO_BACKSLASH_ESCAPE
sql_mode w MySQL lub standard_conforming_strings
conf w PostgreSQL (którym twórcy PostgreSQL grozili już od kilku wersji).
Jedynym prawdziwym rozwiązaniem jest użycie mało znanego LIKE...ESCAPE
składnia określająca wyraźny znak ucieczki dla LIKE
-wzór. Jest to używane zamiast odwrotnego ukośnika w MySQL i PostgreSQL, dzięki czemu są one zgodne z tym, co robią wszyscy inni i dając gwarantowany sposób włączenia znaków spoza pasma. Na przykład z =
znak jako ucieczka:
# 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+'%'))
Działa to na bazach danych zgodnych z PostgreSQL, MySQL i ANSI SQL (oczywiście modulo the paramstyle, który zmienia się w różnych modułach db).
Nadal może występować problem z MS SQL Server/Sybase, który najwyraźniej pozwala również na [a-z]
-style grup znaków w LIKE
wyrażenia. W tym przypadku chciałbyś również uciec przed literałem [
znak z .replace('[', '=[')
. Jednak zgodnie z ANSI SQL escaping znak, który nie wymaga escapingu, jest nieprawidłowy! (Argh!) Więc chociaż prawdopodobnie nadal będzie działać w prawdziwych systemach DBMS, nadal nie będziesz zgodny z ANSI. westchnienie...