Yes, this is a real mess. Both MySQL and PostgreSQL use a backslash by default for this. This is a terrible pain if you again avoid the string using backslashes instead of using parameterization, and are also incorrect according to ANSI SQL: 1992, which says that by default there are no extra escape characters on top of the normal string escaping and therefore there is no way to enable literal % or _ .
I would suggest that a simple backslash method is also wrong if you disable backslash screens (which themselves do not match ANSI SQL) using NO_BACKSLASH_ESCAPE sql_mode in MySQL or standard_conforming_strings conf in PostgreSQL (which PostgreSQL developers are threatening to do for several versions now) .
The only real solution is to use the little-known LIKE...ESCAPE syntax to specify an explicit escape character for the LIKE -pattern. This is used instead of the backslash in MySQL and PostgreSQL, which makes them compatible with what everyone else does, and provides a guaranteed way to include out-of-band characters. For example, with the = sign as 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+'%'))
This works with PostgreSQL, MySQL, and ANSI SQL databases (modulo, which, of course, changes on different db modules).
There may still be a problem with MS SQL Server / Sybase, which apparently also allows [az] -character groups of characters in LIKE expressions. In this case, you also want to avoid the symbol [ c .replace('[', '=[') . However, according to ANSI SQL, escaping characters that do not require escaping is not valid! (Argh!) Therefore, although it will probably still work through real DBMSs, you still will not be ANSI-compatible. Sigh...
bobince Jan 21 2018-10-21T00: 00Z
source share