我见过几个类似的线程,但试图逃避字符并不适合我。
简而言之,我有一个字符串列表,我正在迭代,这样我的目标是构建一个查询,将列表中的许多字符串合并到一个'Select,Like'查询中。
这是我的代码(Python)
def myfunc(self, cursor, var_list):
query = "Select var FROM tble_tble WHERE"
substring = []
length = len(var_list)
iter = length
for var in var_list:
if (iter != length):
substring.append(" OR tble_tble.var LIKE %'%s'%" % var)
else:
substring.append(" tble_tble.var LIKE %'%s'%" % var)
iter = iter - 1
for str in substring:
query = query + str
...
那应该够了。如果从我之前声明的声明中显而易见,我正在尝试 构建一个查询,该查询在列表中运行SQL“LIKE” 比较相关字符串。
感谢您的时间,并随时提出任何问题以便澄清。
答案 0 :(得分:7)
首先,您的问题与SQL无关。扔掉所有与SQL相关的代码并执行此操作:
var = 'foo'
" OR tble_tble.var LIKE %'%s'%" % var
你会得到同样的错误。这是因为您正在尝试%
- 使用带有迷路%
标志的字符串进行格式化。因此,它试图弄清楚如何处理%'
并失败。
你可以逃避这些迷路%
这样的迹象:
" OR tble_tble.var LIKE %%'%s'%%" % var
然而,这可能不是你想要做的。
首先,考虑使用{}
- 格式化而不是%
- 格式化,尤其是当您尝试构建格式化的字符串,其中包含%
个字符他们。它避免了逃避它们的需要。所以:
" OR tble_tble.var LIKE %'{}'%".format(var)
但是,更重要的是,你根本不应该做这种格式化。不要将值格式化为SQL字符串,只需将它们作为SQL参数传递。如果您使用的是sqlite3,请使用?
参数标记;对于MySQL,%s
;对于不同的数据库,请阅读其文档。所以:
" OR tble_tble.var LIKE %'?'%"
这里没有什么可以出错,也没有什么需要逃脱的。当您使用查询字符串调用execute
时,请将[var]
作为参数传递。
这更简单,通常更快,并且巧妙地避免了处理边缘情况的大量愚蠢错误,最重要的是,它可以防止SQL注入攻击。
sqlite3 docs更详细地解释了这一点:
通常,您的SQL操作需要使用Python变量中的值。您不应该使用Python的字符串操作来汇编查询...而是使用DB-API的参数替换。将
?
作为占位符放在要使用值的位置,然后提供值元组作为游标execute()
方法的第二个参数。 (其他数据库模块可能使用不同的占位符,例如%s或:1。)...
最后,正如其他人在评论中指出的那样,在LIKE
条件下,您必须将百分号置于引号内,而不是外部。所以,无论你采用哪种方式解决这个问题,你都会遇到另一个问题需要解决。但那个应该容易多了。 (如果没有,你可以随时回来问另一个问题。)
答案 1 :(得分:0)
您需要像这样转义%
,您需要更改引号以包含%
生成正确的SQL
" OR tble_tble.var LIKE '%%%s%%'"
例如:
var = "abc"
print " OR tble_tble.var LIKE '%%%s%%'" % var
它将被翻译为:
OR tble_tble.var LIKE '%abc%'
答案 2 :(得分:0)
这是一个古老的问题,因此,为了与上述所有软件的最新版本配合使用,我要做的事情是
citp = "SomeText" + "%%" # if your LIKE wants database rows that match start text, else ...
citp = "%%" + "SomeQueryText" + "%%"
chek_copies = 'SELECT id, code, null as num from indicator WHERE code LIKE "%s" AND owner = 1 ;'
check_copies = (chek_copies % (citp))
copies_checked = pd.read_sql(check_copies, con=engine)
像魅力一样工作-但是反复无常