Как python pymysql.cursors получает результат возврата INOUT из хранимой процедуры mysql

#python #mysql #python-3.x #stored-procedures

#python #mysql #python-3.x #хранимые процедуры

Вопрос:

У меня есть mysql proc:

 CREATE DEFINER=`user`@`localhost` PROCEDURE `mysproc`(INOUT  par_a INT(10), IN  par_b VARCHAR(255) , IN  par_c VARCHAR(255), IN  par_etc VARCHAR(255))
    BEGIN
        // bla... insert query here
        SET par_a = LAST_INSERT_ID();
    END$$
DELIMITER ;
  

чтобы проверить этот sp, если я запущу:

 SET @par_a = -1;
SET @par_b = 'one';
SET @par_c = 'two';
SET @par_etc = 'three';

CALL mysproc(@par_a, @par_b, @par_c, @par_etc);
SELECT @par_a;
COMMIT;
  

он возвращает @par_a как то, что я хочу, поэтому я предполагаю, что моя БД в порядке…

затем…

У меня есть python следующим образом:

 import pymysql.cursors

def someFunction(self, args):
        # generate Query
        query = "SET @par_a = %s; 
            CALL mysproc(@par_a, %s, %s, %s); 
            SELECT @par_a 
            commit;"

        try:
            with self.connection.cursor() as cursor:
                cursor.execute(query,(str(par_a), str(par_b), str(par_c), str(par_etc)))
                self.connection.commit()
                result = cursor.fetchone()
                print(result) # <-- it print me 'none' how do i get my @par_a result from mysproc above?
                return result
        except:
            raise
        finally:
            self.DestroyConnection()
  

результат: сохраненный процесс выполнен, как я вижу запись.

проблема: но я не могу получить результат @par_a в моем коде python из mysproc выше?

и, если я изменю:

 # generate Query
query = "SET @par_a = '"   str(-1)   "'; 
    CALL mysproc(@par_a, %s, %s, %s); 
    SELECT @par_a 
    commit;"
  

Для

 # generate Query
query = "SELECT 'test' 
    commit;"
  

и

 cursor.execute(query)
  

как ни странно, это дает мне правильный результат ('test',)

Комментарии:

1. Вы используете cursor.fetchall() или cursor.fetchone() . Вам следует потратить немного времени на чтение документации здесь: pymysql.readthedocs.io/en/latest

2. Спасибо, @Nicarus, нужно ли мне делать «select» в моей переменной запроса в python, чтобы получить результат par_a? или fetchone() будет достаточно умен, чтобы получить мой результат par_a? пока я пытался, python напечатал мне ‘none’ T_T

3. Вам нужно, чтобы запрос возвращал нужные значения. Как только запрос записан для этого, вы используете функции выборки, чтобы вернуть этот результат в Python.

4. @Nicarus, не работает, я обновил свой вопрос и изменил ваш образец документа, но результат продолжает посылать мне «нет»

5. Почему вы пишете свой запрос выше иначе, чем приведенный ниже???

Ответ №1:

Я использовал этот класс и получил ответ.

 import pymysql.cursors

class connMySql:
        def __init__(self, User, Pass, DB, Host='localhost', connShowErr=False, connAutoClose=True):
                self.ShowErr = connShowErr
                self.AutoClose = connAutoClose
                self.DBName = DB
                try:
                        self.connection = pymysql.connect(host=Host,
                             user=User,
                             password=Pass,
                             db=DB, #charset='utf8mb4',
                             cursorclass=pymysql.cursors.DictCursor)
                except ValueError as ValErr:
                        if self.ShowErr == True: print(ValErr)
                        return False

        def Fetch(self, Query):
                try:
                        with self.connection.cursor() as cursor:
                                # Read a single record
                                cursor.execute(Query)
                                result = cursor.fetchall()
                        return result
                except ValueError as ValErr:
                        if self.ShowErr == True: print(ValErr)
                        return False
                finally:
                        if self.AutoClose == True: self.connection.close()

        def Insert(self, Query):
                try:
                        with self.connection.cursor() as cursor:
                                # Create a new record
                                cursor.execute(Query)
                        # connection is not autocommit by default. So you must commit to save
                        # your changes.
                        self.connection.commit()
                except ValueError as ValErr:
                        if self.ShowErr == True: print(ValErr)
                        return False
                finally:
                        if self.AutoClose == True: self.connection.close()

        def ProcedureExist(self, ProcedureName):
                try:
                        result = self.Fetch("SELECT * FROM mysql.proc WHERE db = ""   str(self.DBName)   "";")
                        Result = []
                        for item in result:
                                Result.append(item['name'])
                        if ProcedureName in Result:
                                return True
                        else:
                                return False
                except ValueError as ValErr:
                        if self.ShowErr == True: print(ValErr)
                        return False

        def CallProcedure(ProcedureName, Arguments=""):
                try:
            # Set arguments as a string value
                        result = self.Fetch('CALL '   ProcedureName   '('   Arguments   ')')
                except ValueError as ValErr:
                        if self.ShowErr == True: print(ValErr)
                        return False
                finally:
                        if self.AutoClose == True: self.connection.close()

        def CloseConnection(self):
                try:
                        self.connection.close()
                        return True
                except ValueError as ValErr:
                        if self.ShowErr == True: print(ValErr)
                        return False

def main():
    objMysqlConn = connMySql('user', '1234', 'myDB', connShowErr=True, connAutoClose=False)
    ProcedureName= "mysproc"
    if objMysqlConn.ProcedureExist(ProcedureName):
            result = objMysqlConn.Fetch('CALL '   ProcedureName   '()')
            if result != False:
                    result = result[0]
                    print(result)
    else:
            print("The procecure does not exist!")

if __name__ == '__main__':
    main()