Python 3.8.10更新MySQL分类遇ObjectNotExecutableError的解决问询
解决SQLAlchemy执行UPDATE语句时的ObjectNotExecutableError问题
使用Python 3.8.10结合SQLAlchemy更新MySQL数据库的categories字段时,执行代码触发ObjectNotExecutableError,但生成的SQL语句手动在数据库执行正常。原代码逻辑是遍历DataFrame匹配分类,拼接SQL字符串后执行,报错信息如下:
ObjectNotExecutableError('Not an executable object: \'UPDATE prompts SET categories = \\\'"[\\\\"fashion\\\\", \\\"Painting\\\"]"\\\' WHERE id = 1;\'')
原核心错误代码段:
with engine.connect() as conn: for data in update_list: query = f"UPDATE prompts SET categories = '{data[0]}' WHERE id = {data[1]};" conn.execute(query)
问题原因
SQLAlchemy的Connection.execute()方法要求传入可执行对象(如text包装的SQL语句),而非直接传入字符串。直接拼接字符串不仅触发该错误,还存在SQL注入风险。
解决方案
- 从SQLAlchemy导入
text工具类,用于包装SQL语句 - 使用参数化查询传递数据,避免字符串拼接
修改后的核心代码:
from sqlalchemy import text # ... 其他代码逻辑保持不变 ... if update_list: try: with engine.connect() as conn: # 定义参数化的SQL模板 update_query = text("UPDATE prompts SET categories = :categories WHERE id = :id;") for categories_str, prompt_id in update_list: conn.execute(update_query, {"categories": categories_str, "id": prompt_id}) conn.commit() # 显式提交事务 logging.info("Updated categories successfully.") except SQLAlchemyError as e: logging.error(f"An error occurred: {e}") print(e)
额外优化:批量更新提升效率
如果update_list数据量较大,循环执行单条更新效率较低,可以改用批量更新:
from sqlalchemy import text # ... 其他代码逻辑保持不变 ... if update_list: try: with engine.connect() as conn: # 构造批量更新的参数列表 params = [{"categories": cat_str, "id": pid} for cat_str, pid in update_list] # 批量执行更新语句 conn.execute(text("UPDATE prompts SET categories = :categories WHERE id = :id;"), params) conn.commit() logging.info("Updated categories successfully.") except SQLAlchemyError as e: logging.error(f"An error occurred: {e}") print(e)
关键说明
- 使用
text()包装SQL语句,将其转换为SQLAlchemy可执行对象 - 参数化传递数据,既避免了SQL注入,也解决了字符串转义问题(比如原代码中出现的多层转义)
- 显式调用
conn.commit():SQLAlchemy 2.0+默认使用事务模式,必须手动提交修改才能生效
内容的提问来源于stack exchange,提问作者Carol.Kar
相关产品推荐
相关产品推荐

