我有一个从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 ;
答案 0 :(得分:48)
感谢JoshuaBoshi的回答,解决了这个问题。在调用该过程之后,我必须关闭游标并再次打开它,然后再使用它来执行另一个语句:
cursor.close()
cursor = connection.cursor()
可以在fetchall()
后立即关闭光标。结果集仍然存在,可以循环使用。
答案 1 :(得分:12)
这样做的主要原因是在进行新查询之前未从光标获取的结果。可能有多个结果集。
要停止错误,您必须确保每次使用.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回购 - 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客户端中运行它以查看真正的问题。
答案 2 :(得分:3)
这不是python问题,而是mysql问题。从perl做同样的事情你会得到同样的错误。一般情况下,当我运行mysql控制台,然后从另一个控制台终止它,然后尝试从被杀死的控制台运行查询时,我会看到该消息。
某些事情正在扼杀你的言论之间的联系。这可能是您手术中的错误。检查你的mysql错误日志。
答案 3 :(得分: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()
执行答案 4 :(得分:0)
由于我现在已经在Google上搜索过几次,遇到了同样的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
阻止我取回此信息。