43

我有一个从 Python 执行的 MySQL 存储过程(包装在 Django 中)。当我尝试执行第二条语句时,出现错误“命令不同步;您现在无法运行此命令”。此时我无法提交交易。这只是我调用过程时的问题。该怎么办?

cursor.callproc('my_mysql_procedure', [some_id,]) 
result = cursor.fetchall()
for r in result:
    do something

cursor.execute("select * from some_table")
result = cursor.fetchall()

编辑:我被要求发布 MySQL 程序。我让它变得超级简单,但我仍然看到同样的问题

delimiter $$
create procedure my_mysql_procedure(p_page_id int)
    begin

        select 1
        from dual; 

    end$$
delimiter ;
4

5 回答 5

62

感谢 JoshuaBoshi 的回答,解决了这个问题。调用该过程后,我必须关闭游标并再次打开它,然后才能使用它执行另一条语句:

cursor.close() 

cursor = connection.cursor() 

之后可以立即关闭游标fetchall()。结果集仍然存在并且可以循环通过。

于 2012-07-21T07:21:40.983 回答
17

造成这种情况的主要原因是在进行新查询之前未从游标中获取结果。可能有多个结果集。

要停止错误,您必须确保每次使用 .nextset 使用结果集。如果它产生多个结果集——你甚至可能需要做一些。

cursor.callproc('my_mysql_procedure', [some_id,]) 
result = cursor.fetchall()
for r in result:
    do something
cursor.nextset()
cursor.execute("select * from some_table")
result = cursor.fetchall()

在我的情况下,我发现这实际上可以表明 sql 查询中的其他问题,这些问题在进行后续查询之前不会被选为 python 错误。他们产生了多个结果集。

将此应用于下面的示例(我看到相同的错误),

>>> import MySQLdb
>>> conn = MySQLdb.connect(passwd="root", db="test")
>>> cur = conn.cursor()
>>> cur.execute("insert into foo values (1););")
1L
>>> cur.nextset()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 107, in nextset
    nr = db.next_result()
_mysql_exceptions.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1

这里 - 因为解析错误(一些受信任的输入数据,被代码修改)导致该分号,然后是一个新语句 - 这产生了多个结果集。它不会对这条语句产生错误,但对于下一个试图在游标上运行命令的语句。

我制作了一个 github repo - https://github.com/odmsolutions/mysql_python_out_of_sync_demo - 来演示和测试这一点。


原始答案:查看https://github.com/farcepest/MySQLdb1/issues/28,了解我如何能够通过 3 行代码可靠地重现此问题的详细信息:

重现这个的最小情况:(假设你有一个空白数据库,并且只创建了一个到数据库的连接,称为 conn)

>>> conn.query("Create table foo(bar int(11))")
>>> conn.query("insert into foo values (1););")
>>> conn.query("insert into foo values (2););")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
_mysql_exceptions.ProgrammingError: (2014, "Commands out of sync; you can't run this command now")

这是生成的错误语法,从错误中我无法判断这是问题所在。

尝试按照 Bukzor 的建议检查最后一个查询或过程 - 并尝试在原始 mysql 客户端中运行它以查看真正的问题。

于 2013-09-04T15:48:07.153 回答
4

这不是python问题,而是mysql问题。从 perl 做同样的事情,你会得到同样的错误。通常,我在运行 mysql 控制台时看到该消息,然后从另一个控制台将其终止,然后尝试从终​​止的控制台运行查询。

有些东西正在扼杀你陈述之间的联系。这可能是您的程序中的错误。检查你的mysql错误日志。

于 2012-07-20T16:17:50.730 回答
2

我在运行以下 Python (2.7) 代码时遇到了这个错误:

  def _execute(self, query, params, is_destructive):
try:
  cursor = self.con.cursor()
  cursor.execute(query, params)
  if is_destructive:
    self.con.commit()
  return cursor.fetchall()
finally:
  cursor.close()

问题源于 self.con.commit() 调用。我们是防御性的,并且在关闭游标之前进行了破坏性(写入)操作的编码。MySql 不喜欢这样。删除调用的 commit() 解决了问题,脚本仍然通过 cursor.fetchall() 执行

于 2016-02-27T00:33:07.250 回答
0

由于我现在已经用谷歌搜索了几次,登陆了同一个 SO 问题(这里),并且没有一个答案是有帮助的,这里是我未来的建议:

此错误是 MySQL 未获取响应的来源。也就是说,我们发送了请求,得到了一些东西,但并不关心阅读它。

req = "UPDATE data SET h1='qwertyuioasdasdasda' WHERE id=1;commit;"

就我而言,删除后commit我能够看到此错误:

Warning: (1265L, "Data truncated for column 'h1' at row 1")

之所以提出它是因为我试图写h1的数据类型太长了。但是,commit阻止我取回这些信息。

于 2019-03-05T22:44:41.393 回答