SQLAlchemy操作MSSQL含触发器表报错,求可行解决方案
问题描述
使用SQLAlchemy连接MSSQL 2019数据库,目标表parts存在无法删除的insert/update触发器,执行插入代码时触发以下错误:
The target table 'parts' of the DML statement cannot have any enabled triggers if the statement contains an OUTPUT clause without INTO clause.DB-Lib error message 20018
插入代码如下:
engine_new = create_engine('mssql+pymssql://***:***@***/***', implicit_returning=False) Session_new = sessionmaker(bind=engine_new) session_new = Session_new() metadata_new = MetaData() metadata_new.reflect(bind=engine_new) partsTable = metadata_new.tables['parts'] def addPart(dataArt, manId): # rowInsertStmt = insert(partsTable).values( rowInsertStmt = partsTable.insert().values( part_kod = dataArt.get('kod'), part_description = dataArt.get('title'), part_kod_supplier = dataArt.get('supplier'), part_manufacturer = manId ) session_new.execute(rowInsertStmt) session_new.commit()
注:dataArt为零件描述字典,manId为制造商ID。
解决方案
1. 强制SQLAlchemy不生成OUTPUT子句
你已经在创建引擎时添加了implicit_returning=False,但可能对反射后的表未完全生效,可尝试两种方式补全设置:
- 在insert语句中显式禁用返回值:
修改insert语句,追加.returning(None)强制不生成OUTPUT子句:rowInsertStmt = partsTable.insert().values( part_kod = dataArt.get('kod'), part_description = dataArt.get('title'), part_kod_supplier = dataArt.get('supplier'), part_manufacturer = manId ).returning(None) - 给反射后的表单独设置属性:
在获取反射表后,直接设置表的implicit_returning为False:metadata_new.reflect(bind=engine_new, tables=['parts']) partsTable = metadata_new.tables['parts'] partsTable.implicit_returning = False
2. 改用原生SQL执行插入
如果上述方法仍无法解决,可直接使用原生SQL绕开SQLAlchemy的语句生成逻辑:
from sqlalchemy import text def addPart(dataArt, manId): insert_sql = text(""" INSERT INTO parts (part_kod, part_description, part_kod_supplier, part_manufacturer) VALUES (:kod, :title, :supplier, :man_id) """) session_new.execute(insert_sql, { 'kod': dataArt.get('kod'), 'title': dataArt.get('title'), 'supplier': dataArt.get('supplier'), 'man_id': manId }) session_new.commit()
这种方式完全由你控制SQL语句,不会生成OUTPUT子句,可彻底规避触发器冲突问题。
内容的提问来源于stack exchange,提问作者AnastasWu
相关产品推荐
相关产品推荐

