由于某些奇怪的原因,我无法在Python测试应用程序中获得callproc调用的结果。 MqSQL 5.2.47中的存储过程如下所示:
CREATE PROCEDURE `mytestdb`.`getperson` (IN personid INT)
BEGIN
select person.person_id,
person.person_fname,
person.person_mi,
person.person_lname,
person.persongender_id,
person.personjob_id
from person
where person.person_id = personid;
END
现在,使用PyCharm和Python 3.3,我无法在调用此存储过程时检索任何内容。这段代码得到了我想要的结果:
import mysql.connector
cnx = mysql.connector.connect(user='root', host='127.0.0.1', database='mytestdb')
cnx._open_connection()
cursor = cnx.cursor()
cursor.execute("select * from person where person.person_id = 1")
people = cursor.fetchall()
for person in people:
print(person)
cnx.close()
但是这个代码有cursor.fetchall()或cursor.fetchone()......
import mysql.connector
cnx = mysql.connector.connect(user='root', host='127.0.0.1', database='mytestdb')
cnx._open_connection()
cursor = cnx.cursor()
cursor.callproc("getperson", [1])
people = cursor.fetchall()
for person in people:
print(person)
cnx.close()
...返回“mysql.connector.errors.InterfaceError:没有结果集来取自。”使用cursor.execute()方法还有一个奇怪的行为,就像这样......
import mysql.connector
cnx = mysql.connector.connect(user='root', host='127.0.0.1', database='mytestdb')
cnx._open_connection()
cursor = cnx.cursor()
cursor.execute("call getperson(1)")
people = cursor.fetchall()
for person in people:
print(person)
cnx.close()
...因为它产生“mysql.connector.errors.InterfaceError:对于具有多个查询的语句使用cmd_query_iter”,后跟“mysql.connector.errors.InterfaceError:执行多个语句时使用multi = True”,尽管事实是我只返回一个查询结果而不是多个结果集。 MySQL Python连接器是否将存储过程的执行调用视为双查询?我怎样才能调用存储过程并取回我的结果?我真的不想在我的代码中使用动态SQL。提前感谢任何建议!
答案 0 :(得分:13)
您是否尝试过选择其中一个结果集?
for result in cursor.stored_results():
people = result.fetchall()
即使您只有一个SELECT
stmt,它也可能正在分配多个结果集。我知道在PHP的MySQLi存储过程中这样做是为了允许INOUT和OUT变量返回(再次,你没有,但也许它正在分配)。
我正在使用的完整代码(正在运行)是:
import mysql.connector
cnx = mysql.connector.connect(user='me',password='pw',host='localhost',database='mydb')
cnx._open_connection()
cursor = cnx.cursor()
cursor.callproc("getperson",[1])
for result in cursor.stored_results():
people=result.fetchall()
for person in people:
print person
cnx.close()
答案 1 :(得分:0)
为什么不这样试试呢
cursor.callproc("getperson", ['1'])
答案 2 :(得分:0)
在调用cursor.callproc
之后获取存储过程的结果取决于以下因素:
DBAPI spec在cursor.callproc
上要这样说:
使用给定名称调用存储的数据库过程。参数序列必须为该过程期望的每个参数包含一个条目。调用结果将作为输入序列的修改后的副本返回。输入参数保持不变,输出和输入/输出参数替换为可能的新值。
该过程还可以提供结果集作为输出。然后必须通过标准的.fetch *()方法使它可用。
实际上,只有在过程返回单行且列数与INOUT和OUT参数的数量匹配的情况下,才可以使用cursor.callproc
的返回值,因此结果的方式会有一些差异被处理。
主要的MySQL Python连接器程序包-MySQL Connector,mysqlclient (MySQLdb)和PyMySQL是如何处理这些情况的。
单行结果,通过INOUT或OUT参数返回
MySQL Connector 返回输入序列的修改后的副本作为cursor.callproc
的返回值;该值是一个元组。
params = [in_param, out_param1, out_param2]
in_, out1, out2 = cursor.callproc("test_proc", params)
mysqlclient 和 PyMySQL 要求在数据库中查询输出参数,然后通过游标获取结果;该值是一个元组的元组。要查询的参数名称的格式为'@_{procedure_name}_{params.index(param)}'
cursor.callproc("test_proc", params)
cursor.execute("""SELECT @_test_proc_0, @_test_proc_1""")
result = cursor.fetchall()
单个结果集中的一行或多行,未定义INOUT或OUT参数
MySQL Connector 通过游标的stored_results方法公开结果(cursor.stored_results
不是DBAPI规范的一部分)
cursor.callproc("test_proc", params)
results = [r.fetchall() for r in cursor.stored_results()]
mysqlclient 和 PyMySQL 通过游标的fetch *方法公开结果
cursor.callproc("test_proc", params)
results = cursor.fetchall()
多个结果集,未定义INOUT或OUT参数
MySQL Connector 通过光标的stored_results
方法公开结果
cursor.callproc("test_proc", params)
results = [r.fetchall() for r in cursor.stored_results()]
mysqlclient 和 PyMySQL 要求通过游标获取每个结果集,同时调用cursor.nextset前进到下一个结果集。请注意,可能会返回一个额外的空结果集,这是调用过程的结果(如果通过cursor.nextset
而不是仅一次调用cursor.fetchall
来检索结果,则在前面的示例中也会发生)。
cursor.callproc("test_proc", params)
results = [cursor.fetchall()]
while cursor.nextset():
results.append(cursor.fetchall())
版本信息
$ mysql --version
mysql Ver 15.1 Distrib 10.1.41-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2
$ pip list | grep -i mysql
mysql-connector-python 8.0.18
mysqlclient 1.4.6
PyMySQL 0.9.3