recherche

Maison  >  Questions et réponses  >  le corps du texte

Le curseur Python ne peut pas récupérer les résultats de la procédure stockée

<p>Pour une raison étrange, je ne parviens pas à obtenir les résultats d'un appel callproc dans une application de test Python. La procédure stockée dans MqSQL 5.2.47 ressemble à ceci : </p> <pre class="brush:php;toolbar:false;">CREATE PROCEDURE `mytestdb`.`getperson` (IN personid INT) COMMENCER sélectionnez person.person_id, personne.person_fname, personne.person_mi, personne.person_lname, personne.persongender_id, personne.personjob_id de la personne où personne.person_id = personid ; FIN</pré> <p>Maintenant, en utilisant PyCharm et Python 3.3, je n'arrive pas à récupérer quoi que ce soit lors de l'appel de cette procédure stockée. Ce code obtient le résultat souhaité : </p> <pre class="brush:php;toolbar:false;">importer mysql.connector cnx = mysql.connector.connect(user='root', host='127.0.0.1', database='mytestdb') cnx._open_connection() curseur = cnx.cursor() curseur.execute("sélectionner * de la personne où personne.person_id = 1") personnes = curseur.fetchall() pour personne chez les personnes : imprimer (personne) cnx.close()</pre> <p>Mais ce code a curseur.fetchall() ou curseur.fetchone()...</p> <pre class="brush:php;toolbar:false;">importer mysql.connector cnx = mysql.connector.connect(user='root', host='127.0.0.1', database='mytestdb') cnx._open_connection() curseur = cnx.cursor() curseur.callproc("getperson", [1]) personnes = curseur.fetchall() pour personne chez les personnes : imprimer (personne) cnx.close()</pre> <p>...renvoie "mysql.connector.errors.InterfaceError : Il n'y a aucun jeu de résultats à obtenir." Il y a un comportement étrange supplémentaire en utilisant la méthode curseur.execute(), comme celui-ci... </ p> <pre class="brush:php;toolbar:false;">importer mysql.connector cnx = mysql.connector.connect(user='root', host='127.0.0.1', database='mytestdb') cnx._open_connection() curseur = cnx.cursor() curseur.execute("appeler getperson(1)") personnes = curseur.fetchall() pour personne chez les personnes : imprimer (personne) cnx.close()</pre> <p> ... car il produit "mysql.connector.errors.InterfaceError : utilisation de cmd_query_iter pour les instructions avec plusieurs requêtes" suivi de "mysql.connector.errors.InterfaceError : utilisation de multi=True lors de l'exécution de plusieurs instructions", malgré le fait que je ne renvoie qu’un seul résultat de requête plutôt que plusieurs jeux de résultats. Le connecteur MySQL Python traite-t-il les appels d'exécution aux procédures stockées comme des requêtes doubles ? Comment appeler une procédure stockée et obtenir les résultats ? Je ne veux vraiment pas utiliser du SQL dynamique dans mon code. Merci d'avance pour tout conseil! </p>
P粉833546953P粉833546953459 Il y a quelques jours626

répondre à tous(2)je répondrai

  • P粉523335026

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

    Obtenir le résultat d'une procédure stockée après un appel cursor.callproc dépend des facteurs suivants :

    • Si le résultat de la procédure appelante est affecté au paramètre INOUT ou OUT
    • Que le résultat soit constitué d'une seule ligne ou d'un ensemble de résultats (ou de plusieurs ensembles de résultats)
    • Pack Python pour passer des appels

    DBAPI Spécification dans 上有这样的说法光标.callproc :

    En fait, l'utilisation de la valeur de retour de Cursor.callproc ne fonctionne que si la procédure renvoie une seule ligne et que le nombre de colonnes correspond au nombre de paramètres INOUT et OUT, il y a donc quelques changements dans la façon dont les résultats sont gérés.


    Voici comment les principaux packages de connecteurs MySQL Python gèrent ces situations : MySQL Connector, mysqlclient (MySQLdb)< /a> et PyMySQL. < /p>

    Résultat sur une seule ligne, renvoyé via les paramètres INOUT ou OUT

    • MySQL Connector renvoie une copie modifiée de la séquence d'entrée comme valeur de retour de cursor.callproc ; la valeur est un tuple.

      params = [in_param, out_param1, out_param2]
      in_, out1, out2 = cursor.callproc("test_proc", params)
    • mysqlclient et PyMySQL nécessitent d'interroger la base de données pour les paramètres de sortie, puis d'obtenir les résultats via un curseur ; la valeur est un tuple de tuples. Le nom du paramètre à interroger est sous la forme '@_{procedure_name}_{params.index(param)}'

      cursor.callproc("test_proc", params)
      cursor.execute("""SELECT @_test_proc_0, @_test_proc_1""")
      result = cursor.fetchall()

    Une ou plusieurs lignes dans un seul ensemble de résultats, aucun paramètre INOUT ou OUT n'est défini

    • Connecteur MySQL via la méthode stored_results du curseur (cursor.stored_results ne fait pas partie de la spécification DBAPI)

      cursor.callproc("test_proc", params)
      results = [r.fetchall() for r in cursor.stored_results()]
    • mysqlclient et PyMySQL exposent les résultats via les méthodes fetch* du curseur

      cursor.callproc("test_proc", params)
      results = cursor.fetchall()

    Plusieurs jeux de résultats, aucun paramètre INOUT ou OUT défini

    • MySQL Connector expose les résultats via la stored_results méthode du curseur

      cursor.callproc("test_proc", params)
      results = [r.fetchall() for r in cursor.stored_results()]
    • mysqlclient et PyMySQL nécessitent l'appel de cursor.nextset pour passer à l'ensemble de résultats suivant. Notez qu'un ensemble de résultats vide supplémentaire peut être renvoyé, qui est le résultat de l'appel de la procédure (si cursor.nextset 检索结果集而不是仅调用 <代码>cursor.fetchall est passé une fois).

      cursor.callproc("test_proc", params)
      results = [cursor.fetchall()]
      while cursor.nextset():
          results.append(cursor.fetchall())

    Informations sur la version

    $ 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

    répondre
    0
  • P粉005417748

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

    Avez-vous essayé de sélectionner l'un des ensembles de résultats ?

    for result in cursor.stored_results():
        people = result.fetchall()

    Même si vous n'avez qu'un seul SELECT stmt, il peut allouer plusieurs ensembles de résultats. Je sais que cela est fait dans les procédures stockées MySQLi de PHP pour permettre le retour des variables INOUT et OUT (encore une fois, ce n'est pas le cas, mais peut-être qu'elles sont allouées de toute façon).

    Le code complet que j'utilise (en cours d'exécution) est :

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

    répondre
    0
  • Annulerrépondre