调用 mysql 存储过程时出现 sqlalchemy 错误

sqlalchemy error when calling mysql stored procedure

我在 python 的 MySql 服务器上使用 sqlalchemy 运行 查询。

我用以下方法初始化 sqlalchemy:

engine = create_engine("mysql+mysqlconnector://{user}:{password}@{host}:{port}/{database}".format(**connection_params))
conn = engine.connect()

其中 connection_params 是包含服务器访问详细信息的字典。

我正在运行查询此查询:

SELECT 
new_db.asset_specification.identifier_code, 
new_db.asset_specification.asset_name, 
new_db.asset_specification.asset_type, 
new_db.asset_specification.currency_code, 
new_db.sector_map.sector_description, 
new_db.super_sector_map.super_sector_description, 
new_db.country_map.country_description, 
new_db.country_map.country_macro_area 

FROM new_db.asset_specification 
INNER JOIN new_db.identifier_code_legal_entity_map on new_db.asset_specification.identifier_code = new_db.identifier_code_legal_entity_map.identifier_code 
INNER JOIN new_db.legal_entity_map on projecthf_db.identifier_code_legal_entity_map.legal_entity_code = new_db.legal_entity_map.legal_entity_code 
INNER JOIN new_db.sector_map on new_db.legal_entity_map.legal_entity_sector = new_db.sector_map.sector_code 
INNER JOIN new_db.super_sector_map on projecthf_db.legal_entity_map.legal_entity_super_sector = new_db.super_sector_map.super_sector_code 
INNER JOIN new_db.country_map on new_db.legal_entity_map.legal_entity_country = new_db.country_map.country_code 
WHERE new_db.asset_specification.identifier_code = str_identifier_code;

使用 conn.execute(query)(我将 query 设置为等于上面的字符串)。

这个运行很好。

我试图将我的查询放在存储过程中,例如:

CREATE DEFINER=`root`@`localhost` PROCEDURE `test_anag`(IN str_identifier_code varchar(100))
BEGIN
SELECT 
new_db.asset_specification.identifier_code, 
new_db.asset_specification.asset_name, 
new_db.asset_specification.asset_type, 
new_db.asset_specification.currency_code, 
new_db.sector_map.sector_description, 
new_db.super_sector_map.super_sector_description, 
new_db.country_map.country_description, 
new_db.country_map.country_macro_area 

FROM new_db.asset_specification 
INNER JOIN new_db.identifier_code_legal_entity_map on new_db.asset_specification.identifier_code = new_db.identifier_code_legal_entity_map.identifier_code 
INNER JOIN new_db.legal_entity_map on projecthf_db.identifier_code_legal_entity_map.legal_entity_code = new_db.legal_entity_map.legal_entity_code 
INNER JOIN new_db.sector_map on new_db.legal_entity_map.legal_entity_sector = new_db.sector_map.sector_code 
INNER JOIN new_db.super_sector_map on projecthf_db.legal_entity_map.legal_entity_super_sector = new_db.super_sector_map.super_sector_code 
INNER JOIN new_db.country_map on new_db.legal_entity_map.legal_entity_country = new_db.country_map.country_code 
WHERE new_db.asset_specification.identifier_code = str_identifier_code;

END

我可以 运行 来自 mysql workbench 和 CALL new_db.test_anag('000000') 中的查询编辑器的存储过程,我得到了想要的结果(这是一行)。

现在我尝试 运行:

res = conn.execute("CALL new_db.test_anag('000000')")

但失败并出现以下异常

sqlalchemy.exc.InterfaceError: (mysql.connector.errors.InterfaceError) Use multi=True when executing multiple statements [SQL: "CALL projecthf_db.test_anag('0237400')"]

我环顾四周,但我找不到任何关于这个错误的有用信息,为了我的爱,我无法理解它。我既不是 Mysql 也不是 sqlalchemy(或任何 RDBMS)方面的专家,但这个看起来应该很容易修复。如果需要更多信息,请告诉我。

在此先感谢您的帮助

来自阅读 related question it can be seen that mysql.connector automatically fetches and stores multiple result sets when executing stored procedures producing such, even if only one result set is produced. SQLAlchemy on the other hand does not support multiple result sets – directly. To execute stored procedures use callproc(). To access a DB-API cursor in SQLAlchemy you have to use a raw connection. In case of mysql.connector the produced result sets can be accessed using stored_results():

from contextlib import closing

# Create a raw MySQLConnection
conn = engine.raw_connection()

try:
    # Get a MySQLCursor
    with closing(conn.cursor()) as cursor:
        # Call the stored procedure
        result_args = cursor.callproc('new_db.test_anag', ['000000'])
        # Iterate through the result sets produced by the procedure
        for result in cursor.stored_results():
            result.fetchall()

finally:
    conn.close()