首頁  >  問答  >  主體

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粉833546953445 天前609

全部回覆(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
  • 取消回覆