Der Python-Cursor kann keine Ergebnisse aus einer gespeicherten Prozedur abrufen
P粉833546953
P粉833546953 2023-08-24 14:22:59
0
2
617
<p>Aus irgendeinem seltsamen Grund kann ich keine Ergebnisse von einem Callproc-Aufruf in einer Python-Testanwendung erhalten. Die gespeicherte Prozedur in MqSQL 5.2.47 sieht folgendermaßen aus: </p> <pre class="brush:php;toolbar:false;">CREATE PROCEDURE `mytestdb`.`getperson` (IN personid INT) BEGINNEN Wählen Sie person.person_id aus, person.person_fname, person.person_mi, person.person_lname, person.persongender_id, person.personjob_id von Person wobei person.person_id = personid; ENDE</pre> <p>Mit PyCharm und Python 3.3 kann ich beim Aufrufen dieser gespeicherten Prozedur scheinbar nichts abrufen. Dieser Code liefert das gewünschte Ergebnis: </p> <pre class="brush:php;toolbar:false;">mysql.connector importieren 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() für Person in Menschen: drucken(Person) cnx.close()</pre> <p>Aber dieser Code hat Cursor.fetchall() oder Cursor.fetchone()...</p> <pre class="brush:php;toolbar:false;">mysql.connector importieren 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() für Person in Menschen: drucken(Person) cnx.close()</pre> <p>...gibt „mysql.connector.errors.InterfaceError: Es gibt keine Ergebnismenge zum Abrufen.“ Es gibt ein zusätzliches seltsames Verhalten bei der Verwendung der Cursor.execute()-Methode, wie dieses... </ p> <pre class="brush:php;toolbar:false;">mysql.connector importieren 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() für Person in Menschen: drucken(Person) cnx.close()</pre> <p> ...weil es „mysql.connector.errors.InterfaceError: using cmd_query_iter for Statements with multiple querys“ gefolgt von „mysql.connector.errors.InterfaceError: using multi=True when executing multiple states“ erzeugt, trotz der Tatsache ist, dass ich nur ein Abfrageergebnis und nicht mehrere Ergebnismengen zurückgebe. Behandelt der MySQL-Python-Connector Ausführungsaufrufe an gespeicherte Prozeduren als doppelte Abfragen? Wie rufe ich eine gespeicherte Prozedur auf und erhalte die Ergebnisse? Ich möchte in meinem Code wirklich kein dynamisches SQL verwenden. Vielen Dank im Voraus für jeden Rat! </p>
P粉833546953
P粉833546953

Antworte allen(2)
P粉523335026

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

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

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

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


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

单行结果,通过 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
P粉005417748

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

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()
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage