Jo, tohle je fakt průšvih. MySQL i PostgreSQL k tomu standardně používají zpětné lomítko. To je strašná bolest, pokud také znovu escapujete řetězec pomocí zpětných lomítek místo použití parametrizace, a je to také nesprávné podle ANSI SQL:1992, která říká, že ve výchozím nastavení neexistují žádné další únikové znaky nad normálním escapováním řetězce, a proto není možné zahrnout doslovné %
nebo _
.
Předpokládal bych, že jednoduchá metoda nahrazování zpětným lomítkem se také pokazí, pokud vypnete úniky zpětným lomítkem (které samy nejsou kompatibilní s ANSI SQL) pomocí NO_BACKSLASH_ESCAPE
sql_mode v MySQL nebo standard_conforming_strings
conf v PostgreSQL (což vývojáři PostgreSQL nyní hrozili, že udělají několik verzí).
Jediným skutečným řešením je použití málo známého LIKE...ESCAPE
syntaxe k určení explicitního znaku escape pro LIKE
-vzor. To se používá místo zpětného lomítka v MySQL a PostgreSQL, čímž se přizpůsobí tomu, co dělají všichni ostatní, a poskytuje zaručený způsob, jak zahrnout znaky mimo pásmo. Například pomocí =
podepsat jako únik:
# 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+'%'))
Toto funguje na databázích kompatibilních s PostgreSQL, MySQL a ANSI SQL (modulo paramstyle samozřejmě, který se mění na různých db modulech).
Stále může být problém s MS SQL Server/Sybase, který zjevně také umožňuje [a-z]
-style skupiny znaků v LIKE
výrazy. V tomto případě byste také chtěli uniknout doslovnému [
znak s .replace('[', '=[')
. Nicméně podle ANSI SQL je escapování znaku, který nepotřebuje escapování, neplatné! (Argh!) Takže ačkoli to bude pravděpodobně stále fungovat ve skutečných DBMS, stále byste nebyli kompatibilní s ANSI. povzdech...