首页  >  问答  >  正文

Python 游标无法从存储过程检索结果

<p>出于某种奇怪的原因,我无法从 Python 测试应用程序中的 callproc 调用中获取结果。 MqSQL 5.2.47 中的存储过程如下所示:</p> <pre class="brush:php;toolbar:false;">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</pre> <p>现在,使用 PyCharm 和 Python 3.3,在调用此存储过程时我似乎无法检索任何内容。这段代码得到了我想要的结果:</p> <pre class="brush:php;toolbar:false;">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()</pre> <p>但是这段代码带有cursor.fetchall()或cursor.fetchone()...</p> <pre class="brush:php;toolbar:false;">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()</pre> <p>...返回“mysql.connector.errors.InterfaceError:没有可从中获取的结果集。”使用cursor.execute()方法还有一个额外的奇怪行为,就像这样......</p> <pre class="brush:php;toolbar:false;">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()</pre> <p> ...因为它产生“mysql.connector.errors.InterfaceError:对具有多个查询的语句使用cmd_query_iter”,然后是“mysql.connector.errors.InterfaceError:执行多个语句时使用multi=True”,尽管事实上我只返回一个查询结果而不是多个结果集。 MySQL Python 连接器是否将对存储过程的执行调用视为双重查询?我如何调用存储过程并获取结果?我真的不想在我的代码中使用动态 SQL。提前感谢您的任何建议!</p>
P粉833546953P粉833546953422 天前582

全部回复(2)我来回复

  • P粉523335026

    P粉5233350262023-08-25 11:31:10

    调用cursor.callproc后获取存储过程的结果取决于以下因素:

    • 调用过程的结果是否分配给 INOUT 或 OUT 参数
    • 结果是由单行还是一个结果集(或多个结果集)组成
    • 用于进行调用的 python 包

    DBAPI 规范 上有这样的说法光标.callproc

    实际上,只有当过程返回单行且列数与 INOUT 和 OUT 参数的数量匹配时,使用 Cursor.callproc 的返回值才有效,因此存在一些问题结果处理方式的变化。


    以下是主要 MySQL Python 连接器包处理这些情况的方式 - MySQL 连接器mysqlclient (MySQLdb)< /a> 和 PyMySQL。< /p>

    单行结果,通过 INOUT 或 OUT 参数返回

    • MySQL Connector 返回输入序列的修改副本作为 cursor.callproc 的返回值;该值是一个元组。

      params = [in_param, out_param1, out_param2]
      in_, out1, out2 = cursor.callproc("test_proc", params)
    • mysqlclientPyMySQL要求查询数据库获取输出参数,然后通过游标获取结果;该值是元组的元组。要查询的参数名称的形式为'@_{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()]
    • mysqlclientPyMySQL 通过游标的 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()]
    • mysqlclientPyMySQL 要求在调用 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

    回复
    0
  • P粉005417748

    P粉0054177482023-08-25 10:38:33

    您是否尝试过选择其中一个结果集?

    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()

    回复
    0
  • 取消回复