Python: SQLAlchemy извлечение имен столбцов и данных из набора данных, возвращаемого хранимой процедурой MySQL.

Используя библиотеку SQLAlchemy для Python, как запустить хранимую процедуру MySQL и извлечь имена столбцов и данные из набора данных, возвращаемого хранимой процедурой.

Я использую библиотеку SQLAlchemy в течение небольшого… Научиться запускать с ее помощью хранимые процедуры MySQL оказалось не так уж сложно. Однако я чувствую, что бывает трудно найти информацию по некоторым аспектам этой библиотеки… Лично для меня она, безусловно, является самой сложной библиотекой баз данных для изучения.

Мне потребовалось немного поиска, чтобы получить возможность извлекать имена столбцов из набора данных, возвращаемого хранимой процедурой MySQL… Решения, предложенные в некоторых сообщениях, на которые я наткнулся, не сработали для меня. Единственное, которое работает, это Вызов хранимой процедуры MySQL на python с именами полей от пользователя mathieu FERAUD. Я документирую это с помощью упрощенного примера хранимой процедуры.

Ниже приведена упрощенная версия хранимой процедуры MySQL, она возвращает только одну строку, но это несущественно:

delimiter //

drop procedure if exists DemoStoredProc; //

create procedure DemoStoredProc( userId int, timesheetId int, 
                                 searchType varchar(10), roundDir varchar(4) )
                                 reads sql data
begin
  declare TOTAL_HOURS int;
  declare TOTAL_MINUTES int;
  declare ROUNDED_HOUR float(5,2);  

  set TOTAL_HOURS = 11;
  set TOTAL_MINUTES = 44;  
  set ROUNDED_HOUR = 0.5;  

  select TOTAL_HOURS, TOTAL_MINUTES, TOTAL_HOURS + ROUNDED_HOUR as ROUNDED_TOTAL_HOURS;  
end; //
Войти в полноэкранный режим Выход из полноэкранного режима

Пример Python, сценарий не делает никаких предположений о том, сколько строк будет в конечном наборе данных.

File sqlalchemy-stored-proc.py:
Войти в полноэкранный режим Выход из полноэкранного режима
from sqlalchemy import create_engine
from contextlib import closing

engine = create_engine( 'mysql+mysqlconnector://behai1:password@localhost/ompdev1', echo = False )
connection = engine.raw_connection()

try:
    with closing( connection.cursor() ) as cursor:
        cursor.callproc( 'DemoStoredProc', [ 1, 111, 'all', 'down' ] )

        result = next( cursor.stored_results() )
        dataset = result.fetchall()
        has_data = len( dataset ) > 0

        if has_data:
            """
            Copying columns names into a list.

            Reference:
                https://dba.stackexchange.com/questions/198216/calling-mysql-stored-procedure-in-python-with-field-names
                Calling MySQL stored procedure in python with field names

                mathieu FERAUD -- https://dba.stackexchange.com/users/207207/mathieu-feraud
            """

            for column_id in cursor.stored_results():
                columns_properties = ( column_id.description )
                columns = [ column[0] for column in columns_properties ]

            data = []
            for row in dataset:
                record = {}
                for idx, name in enumerate( columns ):
                    record[ name ] = row[ idx ]
                data.append( record )

except Exception as e:
    has_data = False
    print( 'Exception. Type {}', type(e), '--', str(e) )
finally:
    if 'result' in locals():
        result.close()

    if 'conn' in locals():
        conn.close()

    if has_data:
        import pprint
        print( 'n' )
        pprint.pprint( data )
    else:
        print( 'nI am sorry...there is no data to print.n' )
Войти в полноэкранный режим Выход из полноэкранного режима

По сути, каждая строка превращается в словарь с именами столбцов в качестве имен ключей. Затем словарь добавляется в список. Наконец, список выводится на печать.

Прежде чем я смог извлечь имена столбцов, у меня уже было готово все остальное. Я не знал и не мог найти информацию, указывающую на cursor.stored_results().

У других, из сообщений, которые я читал в поисках решения, похоже, тоже была такая же проблема… и даже путаница, где предлагался хак. Есть пост, в котором предлагается использовать cursor.description, я попробовал это:

...
    with closing( connection.cursor() ) as cursor:
        cursor.callproc( 'DemoStoredProc', [1, 111, 'all', 'up'] )

        for field in cursor.description:
            print( field )
...         
Войти в полноэкранный режим Выйти из полноэкранного режима
('DemoStoredProc_arg1', 8, None, None, None, None, 1, 32896, 63)
('DemoStoredProc_arg2', 8, None, None, None, None, 1, 32896, 63)
('DemoStoredProc_arg3', 251, None, None, None, None, 1, 0, 255)
('DemoStoredProc_arg4', 251, None, None, None, None, 1, 0, 255)
Войти в полноэкранный режим Выйти из полноэкранного режима
It is the stored procedure's argument information, not the 
returned column name information.
Войти в полноэкранный режим Выйти из полноэкранного режима

Мы можем запустить вышеприведенный скрипт с:

(venv) F:project_xyz>venvScriptspython.exe sqlalchemy-stored-proc.py
Войти в полноэкранный режим Выйти из полноэкранного режима

И мы получим ожидаемый результат:

[{'ROUNDED_TOTAL_HOURS': 11.5, 'TOTAL_HOURS': 11, 'TOTAL_MINUTES': 44}]
Войти в полноэкранный режим Выход из полноэкранного режима

Я надеюсь, что эта статья была вам полезна. Спасибо за прочтение. Счастливого программирования и оставайтесь в безопасности.

Оцените статью
devanswers.ru
Добавить комментарий