【问题标题】:Python MySQL connector - unread result found when using fetchonePython MySQL连接器-使用fetchone时发现未读结果
【发布时间】:2015-06-28 14:55:27
【问题描述】:

我正在将 JSON 数据插入 MySQL 数据库

我正在解析 JSON,然后使用 python 连接器将其插入 MySQL 数据库

通过试用,我可以看到错误与这段代码有关

for steps in result['routes'][0]['legs'][0]['steps']:
    query = ('SELECT leg_no FROM leg_data WHERE travel_mode = %s AND Orig_lat = %s AND Orig_lng = %s AND Dest_lat = %s AND Dest_lng = %s AND time_stamp = %s')
    if steps['travel_mode'] == "pub_tran":
        travel_mode = steps['travel_mode']
        Orig_lat = steps['var_1']['dep']['lat']
        Orig_lng = steps['var_1']['dep']['lng']
        Dest_lat = steps['var_1']['arr']['lat']
        Dest_lng = steps['var_1']['arr']['lng']
        time_stamp = leg['_sent_time_stamp'] 
    if steps['travel_mode'] =="a_pied":
        query = ('SELECT leg_no FROM leg_data WHERE travel_mode = %s AND Orig_lat = %s AND Orig_lng = %s AND Dest_lat = %s AND Dest_lng = %s AND time_stamp = %s')
        travel_mode = steps['travel_mode']
        Orig_lat = steps['var_2']['lat']
        Orig_lng = steps['var_2']['lng']
        Dest_lat = steps['var_2']['lat']
        Dest_lng = steps['var_2']['lng']
        time_stamp = leg['_sent_time_stamp']
    cursor.execute(query,(travel_mode, Orig_lat, Orig_lng, Dest_lat, Dest_lng, time_stamp))
    leg_no = cursor.fetchone()[0]
    print(leg_no)

我已插入更高级别的详细信息,现在正在搜索数据库以将此较低级别的信息与其父级相关联。找到这个唯一值的唯一方法是通过带有时间戳的起点和终点坐标进行搜索。我相信逻辑是合理的,通过在本节之后立即打印 leg_no,我可以看到在第一次检查时出现的值是正确的

但是,当添加到代码的其余部分时,它会导致使用光标插入更多数据的后续部分失败并出现此错误 -

    raise errors.InternalError("Unread result found.")
mysql.connector.errors.InternalError: Unread result found.

问题似乎类似于MySQL Unread Result with Python

查询太复杂需要拆分还是有其他问题?

如果查询确实太复杂,谁能建议如何最好地拆分它?

编辑根据@Gord 的帮助,我尝试转储任何未读结果

cursor.execute(query,(leg_travel_mode, leg_Orig_lat, leg_Orig_lng, leg_Dest_lat, leg_Dest_lng))
            leg_no = cursor.fetchone()[0]
            try:
                cursor.fetchall()
            except mysql.connector.errors.InterfaceError as ie:
                if ie.msg == 'No result set to fetch from.':
                    pass
                else:
                    raise
            cursor.execute(query,(leg_travel_mode, leg_Orig_lat, leg_Orig_lng, leg_Dest_lat, leg_Dest_lng, time_stamp))

但是,我还是得到了

raise errors.InternalError("Unread result found.")
mysql.connector.errors.InternalError: Unread result found.
[Finished in 3.3s with exit code 1]

抓头

编辑 2 - 当我打印 ie.msg 时,我得到 -

No result set to fetch from

【问题讨论】:

  • 您是否在遍历结果集,并使用结果再次查询数据库?您是否为此使用相同的光标?那么对第一个使用缓冲游标可能会很好。对于戈德的回答,我没有什么要补充的了。

标签: python mysql


【解决方案1】:

我能够重现您的问题。如果您检索多行并且在关闭游标或使用它来检索其他内容之前不获取所有行,MySQL 连接器/Python 显然不喜欢它。例如

import mysql.connector
cnxn = mysql.connector.connect(
    host='127.0.0.1',
        user='root',
        password='whatever',
        database='mydb')
crsr = cnxn.cursor()
crsr.execute("DROP TABLE IF EXISTS pytest")
crsr.execute("""
CREATE TABLE pytest (
    id INT(11) NOT NULL AUTO_INCREMENT,
    firstname VARCHAR(20),
    PRIMARY KEY (id)
    )
""")
crsr.execute("INSERT INTO pytest (firstname) VALUES ('Gord')")
crsr.execute("INSERT INTO pytest (firstname) VALUES ('Anne')")
cnxn.commit()
crsr.execute("SELECT firstname FROM pytest")
fname = crsr.fetchone()[0]
print(fname)
crsr.execute("SELECT firstname FROM pytest")  # InternalError: Unread result found.

如果您只期望(或关心)一行,那么您可以在查询中添加 LIMIT

crsr.execute("SELECT firstname FROM pytest LIMIT 0, 1")
fname = crsr.fetchone()[0]
print(fname)
crsr.execute("SELECT firstname FROM pytest")  # OK now

或者您可以使用fetchall() 在完成对检索到的行的处理后删除任何未读结果。

crsr.execute("SELECT firstname FROM pytest")
fname = crsr.fetchone()[0]
print(fname)
try:
    crsr.fetchall()  # fetch (and discard) remaining rows
except mysql.connector.errors.InterfaceError as ie:
    if ie.msg == 'No result set to fetch from.':
        # no problem, we were just at the end of the result set
        pass
    else:
        raise
crsr.execute("SELECT firstname FROM pytest")  # OK now

【讨论】:

  • 感谢@Gord 的宝贵时间!有趣的。所以,我关心的不止一行,所以对查询的限制是行不通的。我正在尝试 fetchall 方法。但是,我得到与以前完全相同的错误:s。我已经编辑了我的答案以反映这一点。有任何想法吗?再次感谢,格里
  • fetchall() 删除任何未读结果”非常有帮助。
  • 与选定的答案相比,我认为这个答案更有意义并解决了问题,而不是绕过它。
【解决方案2】:

只需要buffered to be set to true!

cursor = cnx.cursor(buffered=True)

原因是没有缓冲游标,结果是“延迟”加载的,这意味着“fetchone”实际上只从查询的完整结果集中获取一行。当您再次使用相同的游标时,它会抱怨您仍有 n-1 个结果(其中 n 是结果集数量)等待获取。但是,当您使用缓冲游标时,连接器会在后台获取所有行,而您只需从连接器中取出一个,这样 mysql 数据库就不会抱怨。

【讨论】:

  • 非常感谢,您节省了潜在的错误搜索时间。为什么这有效,解释是什么?
  • 原因是没有缓冲游标,结果是“延迟”加载的,这意味着“fetchone”实际上只从查询的完整结果集中获取一行。当您再次使用相同的游标时,它会抱怨您仍有 n-1 个结果(其中 n 是结果集数量)等待获取。但是,当您使用缓冲游标时,连接器会在后台获取所有行,而您只需从连接器中取出一个,这样 mysql 数据库就不会抱怨。希望对您有所帮助。
  • 使用buffered=True 的额外理由:它使 .rowcount 从一开始就返回总数。见dev.mysql.com/doc/connector-python/en/…
  • ilaif 的评论很好地解释了这一点。但值得一提的是,这个解决方案只是绕过了错误。您可能需要确定 fetchone 是否适合给定完整的结果集,无论是预期的还是意外的,以避免任何潜在问题。
  • 请将此作为更好的答案,这样人们就不必阅读 cmets。
【解决方案3】:

您与 MySQL Workbench 的连接也有可能断开。再次建立连接。这解决了我的问题。

【讨论】:

    【解决方案4】:

    在for循环中设置光标,执行它,然后在循环中再次关闭它有帮助吗? 喜欢:

    for steps in result['routes'][0]['legs'][0]['steps']:
        cursor = cnx.cursor()
        ....
        leg_no = cursor.fetchone()[0]
        cursor.close()
        print(leg_no)
    

    【讨论】:

    • 我测试了用未读行关闭游标,并没有阻止以下查询的异常。
    【解决方案5】:

    cursor.reset() 真的是你想要的......

    fetch_all() 不好,因为您最终可能会将不必要的数据从数据库移动到您的客户端

    【讨论】:

    • 对于 mysql_connector_python-8.0.26,至少, cursor.reset() 有效,而 cursor.close() 无效。奇怪的是我找不到这方面的文档。使用缓冲连接并不是每个人的最佳解决方案,因此将其构建到光标迭代中是最好的方法。尝试:在光标中记录:做事;除了:cursor.reset();提高
    猜你喜欢
    • 1970-01-01
    • 2013-02-26
    • 2014-11-08
    • 1970-01-01
    • 2019-06-05
    • 2016-11-15
    • 2014-03-25
    • 2018-02-28
    • 2018-10-31
    相关资源
    最近更新 更多