Python/String中的“ValueError:不支持的格式字符''(0x22)位于…”

2024-04-19 18:18:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我见过一些类似的线程,但是试图转义字符对我来说不起作用。

简言之,我有一个字符串列表,我正在遍历它,这样我的目标是构建一个查询,将列表中的任意多个字符串合并到一个“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”比较。

感谢您的时间,请随时提出任何问题以澄清。


Tags: 字符串in列表forvarsubstringqueryselect
2条回答

您需要像这样转义%您需要更改引号以包含这两个%生成正确的SQL

" OR tble_tble.var LIKE '%%%s%%'"

例如:

var = "abc"
print " OR tble_tble.var LIKE '%%%s%%'" % var

它将被翻译为:

OR tble_tble.var LIKE '%abc%'

首先,您的问题与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更详细地解释了这一点:

Usually your SQL operations will need to use values from Python variables. You shouldn’t assemble your query using Python’s string operations… Instead, use the DB-API’s parameter substitution. Put ? as a placeholder wherever you want to use a value, and then provide a tuple of values as the second argument to the cursor’s execute() method. (Other database modules may use a different placeholder, such as %s or :1.) …


最后,正如其他人在评论中指出的,在LIKE条件下,必须将百分号放在引号内,而不是放在外。所以,不管你用什么方法解决这个问题,你都会有另一个问题要解决。但那应该容易得多。(如果没有,你可以回来问另一个问题。)

相关问题 更多 >