Ja, det er et rigtig rod. Både MySQL og PostgreSQL bruger som standard backslash-escapes til dette. Dette er en forfærdelig smerte, hvis du også undslipper strengen igen med omvendte skråstreg i stedet for at bruge parameterisering, og det er også forkert ifølge ANSI SQL:1992, som siger, at der som standard ikke er ekstra escape-tegn oven på normal streng-escape, og derfor ingen måde at inkludere en bogstavelig %
eller _
.
Jeg vil antage, at den simple backslash-replace-metode også går galt, hvis du deaktiverer backslash-escapes (som i sig selv ikke er kompatible med ANSI SQL), ved hjælp af NO_BACKSLASH_ESCAPE
sql_mode i MySQL eller standard_conforming_strings
conf i PostgreSQL (hvilket PostgreSQL-udviklerne har truet med at gøre i et par versioner nu).
Den eneste rigtige løsning er at bruge den lidet kendte LIKE...ESCAPE
syntaks for at angive et eksplicit escape-tegn for LIKE
-mønster. Dette bliver brugt i stedet for backslash-escape i MySQL og PostgreSQL, hvilket gør dem i overensstemmelse med, hvad alle andre gør, og giver en garanteret måde at inkludere out-of-band-karaktererne på. For eksempel med =
tegn som en 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+'%'))
Dette virker på PostgreSQL, MySQL og ANSI SQL-kompatible databaser (modulo paramstyle selvfølgelig, som ændres på forskellige db moduler).
Der kan stadig være et problem med MS SQL Server/Sybase, som tilsyneladende også tillader [a-z]
-stil tegngrupper i LIKE
udtryk. I dette tilfælde ønsker du også at undslippe den bogstavelige [
tegn med .replace('[', '=[')
. Men ifølge ANSI SQL er escape et tegn, der ikke behøver escape, ugyldigt! (Argh!) Så selvom det sandsynligvis stadig vil fungere på tværs af rigtige DBMS'er, ville du stadig ikke være ANSI-kompatibel. suk...