【问题标题】:Python: Escape Single Quote from MySQL QueryPython:从 MySQL 查询中转义单引号
【发布时间】:2013-04-27 15:20:18
【问题描述】:

我有一个在循环中运行的查询字符串,并且对于列表查询中的每个项目都会执行。该列表包含字符串,我使用 python 字符串格式技术将查询替换为列表中的相应字符串作为迭代进度。

我已将查询与列表中的字符串一起进行了统一编码:这是我的统一查询:

query = ur'''SELECT something FROM some_table WHERE some_name LIKE "{this_name}%"'''

在执行之前,我将查询字符串编码为utf-8

            try:
                formatted_query = query.format(this_name=list_name)
                #encode the query
                encoded_q = formatted_query.encode('utf-8')
                # execute the query
                self.dbCursor.execute(encoded_q)
                row = self.dbCursor.fetchone()
            except Exception, e:
                traceback.print_exc()

但问题是有时我会遇到列表中包含单引号示例的字符串:foo's。我已经使用 utf-8 进行了 unicode,我认为这样做我不必担心这样的情况。但我收到 sql 错误,因为 MySQL 没有跳过单引号。

我的下一个尝试是替换单引号:

format_string = u"foo's".replace(u"'",u"\'")

但这也不起作用。我还看到this question 的答案是使用我不知道的mysqldb 库内置功能,所以我寻求stackoverflow 社区的帮助来解决这个问题。

我更改代码以反映答案中建议的解决方案,但结果相同:更改如下:

args = [u"{this_name}%".format(this_name=format_name)]
self.dbCursor.execute(query.encode('utf-8'), args)

#error 在这一行被抛出:

错误:

UnicodeEncodeError: 'latin-1' codec can't encode character u'\u014d' in position 4: ordinal not in range(256)

这是错误所抱怨的字符串,我已经检查了该字符串的类型,它是一个 unicode 字符串。

this_name= Sentōkisei type= <type 'unicode'>

【问题讨论】:

  • 如果删除原始标志会发生什么?
  • 不太明白你的意思

标签: python unicode utf-8 mysql-python


【解决方案1】:

如果您使用两个参数调用dbCursor.execute,您的数据库适配器将为您引用这些参数。详情见DB-API specification

query = u'''SELECT something FROM some_table WHERE some_name LIKE %s'''
args = [u"{this_name}%".format(this_name=list_name)]
self.dbCursor.execute(query, args)

query 中的%sparameter marker。它将被args 中给出的带引号的参数替换。要使用的正确参数标记取决于您的数据库适配器。例如,MySQLdb 使用%s,而oursqlsqlite3 使用?

推荐使用参数化 SQL。你真的不应该自己引用这些论点。


关于错误,你贴出来

this_name= Sentōkisei type= <type 'unicode'>

我假设这意味着 format_name 是 unicode。因此,

args = [u"{this_name}%".format(this_name=format_name)]

将使args 成为一个包含一个unicode 的列表。

现在我们到达引发错误的行:

self.dbCursor.execute(query.encode('utf-8'), args)

query 已经是unicode。如果你对该 unicode 进行编码,那么它就变成了str。所以query.encode('utf-8')str,但argsunicode 的列表。我不确定你为什么要编码query,但你的数据库适配器应该能够接受两个 unicode 参数。所以试试

self.dbCursor.execute(query, args)

现在,在重新阅读您的 cmets 后,您似乎已经尝试过了,但它也会引发同样的错误:

UnicodeEncodeError: 'latin-1' codec can't encode character u'\u014d' in position 75: ordinal not in range(256)

我不确定为什么当您想要 utf-8 时,DB 适配器会尝试使用 latin-1 对 unicode 进行编码。最好的解决方案是追踪latin-1 的选择来自哪里。

一个 hacky 解决方法是尝试自己对字符串进行编码:

query = u'''SELECT something FROM some_table WHERE some_name LIKE %s'''.encode('utf-8')
args = [u"{this_name}%".format(this_name=list_name).encode('utf-8')]
self.dbCursor.execute(query, args)

但让我强调一下,我真的不认为这是最好的方法,也不应该这样做。

【讨论】:

  • 所以,我不需要这样做:encoded_q = formatted_query.encode('utf-8')?
  • 关于Unicode,我觉得"{this_name}%"需要换成u"{this_name}%"
  • 我认为是这样,因为使用建议的解决方案,我得到了以下结果:`UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in position 1: ordinal not in range(128) 因为我必须处理像这样的字符串 Hój type= 但我检查了类型,并且在此之前我已经对其进行了统一编码。
  • @unutbu 实际上,我使用您的解决方案运行了我的代码,并与我的代码进行了比较,看看它们在哪里失败,它们都在同一个字符串中失败:UnicodeEncodeError: 'latin-1' codec can't encode character u'\u014d' in position 75: ordinal not in range(256) format_strange_user= Sentōkisei type= &lt;type 'unicode'&gt; 我也对你的代码做了一些小改动,但这确实没有我认为没有任何区别。我编辑了答案以反映这一点。
  • 请发布您正在运行的修改后的代码,以及完整的回溯错误消息。除其他外,它会告诉我们究竟是哪一行产生了错误。
【解决方案2】:

我在这里添加了一个类似问题的答案,你也可以看看!

链接:https://stackoverflow.com/a/61042304/8939258

【讨论】:

    【解决方案3】:

    我放弃了逃避它。相反,我将单引号替换为通配符 %

    text = "woman's"
    text = text.replace("'","%")
    

    在mysql中完美运行

    【讨论】:

      猜你喜欢
      • 2017-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-01
      • 2012-10-05
      相关资源
      最近更新 更多