EMP*_*EMP 31 python postgresql psycopg2 python-db-api
psycopg2是否有一个函数来转义Postgres 的LIKE操作数的值?
例如,我可能想要匹配以字符串"20%of all"开头的字符串,所以我想写这样的东西:
sql = '... WHERE ... LIKE %(myvalue)s'
cursor.fetchall(sql, { 'myvalue': escape_sql_like('20% of all') + '%' }
Run Code Online (Sandbox Code Playgroud)
我可以在这里插入一个现有的escape_sql_like函数吗?
(类似的问题如何显式引用字符串值(Python DB API/Psycopg2),但我找不到答案.)
bob*_*nce 29
是的,这真是一团糟.默认情况下,MySQL和PostgreSQL都使用反斜杠转义.如果您还使用反斜杠而不是使用参数化再次转义字符串,这是一个可怕的痛苦,根据ANSI SQL:1992,它也是不正确的,它表示在正常字符串转义的基础上默认没有额外的转义字符,并且因此无法包含文字%或文字_.
我假设简单的反斜杠替换方法也会出错,如果你关闭反斜杠转义(它本身不符合ANSI SQL),NO_BACKSLASH_ESCAPE在MySQL中使用sql_mode或standard_conforming_strings在PostgreSQL中使用conf(PostgreSQL开发人员一直威胁要这样做)现在有两个版本).
唯一真正的解决方案是使用鲜为人知的LIKE...ESCAPE语法为LIKE-pattern 指定显式转义字符.这被用来代替MySQL和PostgreSQL中的反斜杠转义,使它们符合其他人的所作所为,并提供一种保证包含带外字符的方法.例如,将=符号作为转义:
# 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+'%'))
Run Code Online (Sandbox Code Playgroud)
这适用于PostgreSQL,MySQL和ANSI SQL兼容的数据库(模块化当然是在不同的数据库模块上发生变化的模式).
MS SQL Server/Sybase可能仍然存在问题,这显然也允许表达式中的[a-z]样式字符组LIKE.在这种情况下,您还希望转义文字[字符.replace('[', '=[').但是根据ANSI SQL转义,不需要转义的字符无效!(唉!)虽然它可能仍然适用于真正的DBMS,但你仍然不符合ANSI标准.叹...
小智 22
我能够%通过%%在LIKE操作数中使用来逃脱。
sql_query = "select * from mytable where website like '%%.com'"
cursor.fetchall(sql_query)
Run Code Online (Sandbox Code Playgroud)
如果您使用准备好的语句,那么输入将被包装''以防止 SQL 注入。这很棒,但也阻止了输入 + sql 连接。
解决这个问题的最佳和最安全的方法是将%(s) 作为输入的一部分传递。
cursor.execute('SELECT * FROM goats WHERE name LIKE %(name)s', { 'name': '%{}%'.format(name)})
Run Code Online (Sandbox Code Playgroud)
您也可以从另一个角度看待这个问题。你想要什么?您需要一个查询,该查询对任何字符串参数都通过在参数后附加一个'%'来执行LIKE。在不诉诸功能和psycopg2扩展的情况下,表达这一点的一种好方法是:
sql = "... WHERE ... LIKE %(myvalue)s||'%'"
cursor.execute(sql, { 'myvalue': '20% of all'})
Run Code Online (Sandbox Code Playgroud)
我找到了一个更好的技巧。只需将“%”附加到您的搜索查询文本中即可。
con, queryset_list = psycopg2.connect(**self.config), None
cur = con.cursor(cursor_factory=RealDictCursor)
query = "SELECT * "
query += " FROM questions WHERE body LIKE %s OR title LIKE %s "
query += " ORDER BY questions.created_at"
cur.execute(query, ('%'+self.q+'%', '%'+self.q+'%'))
Run Code Online (Sandbox Code Playgroud)
到目前为止还没有找到内置函数,我编写的函数非常简单:
def escape_sql_like(s):
return s.replace('\\', '\\\\').replace('%', '\\%').replace('_', '\\_')
Run Code Online (Sandbox Code Playgroud)