Используя библиотеку 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}]
Я надеюсь, что эта статья была вам полезна. Спасибо за прочтение. Счастливого программирования и оставайтесь в безопасности.