始终使用' implicit_returning'在SQLAlchemy中有错误的潜在缺陷?
我在处理定义了触发器的MSSQL表时遇到过多次问题,而且由于DB处于复制状态,所有表都有触发器,只能通过放置' implicit_returning&#来解决。 39;:表格中的假。
我现在不确定问题究竟是什么,它与自动增量字段有关,可能是因为我预取了自动增量值,所以我可以将它插入另一个表中。
如果我没有设置“hidden_returning”'当我尝试插入值时,表格为False我得到一个错误,说明当触发器存在或某事时我不能使用RETURNING语句。如果需要,我可以用c / p确切的文字。
那么如果我将table_args放在所有映射类中只是为了安全起见呢?
对我来说特别令人沮丧的是我用于开发的本地数据库&测试不在复制中,并且不需要该选项,但生产数据库是复制的,因此当我部署更改时,它们有时不起作用。 :)
答案 0 :(得分:0)
您可能已经知道,SQLAlchemy Docs中描述了造成困境的原因:
SQLAlchemy默认情况下使用
OUTPUT INSERTED
来获取新生成的 通过IDENTITY
列或其他服务器端的主键值 默认值。 MS-SQL不允许在OUTPUT INSERTED
上使用 有触发器的表。禁用OUTPUT INSERTED
的使用 在每张表的基础上,为每个表指定implicit_returning=False
有触发器的表。
如果您将SQLAlchemy引擎设置为回显SQL,则默认情况下,它将执行以下操作:
INSERT INTO [table] (id, ...) OUTPUT inserted.[id] VALUES (...)
但是,如果您禁用implicit_returning
,则会执行以下操作:
INSERT INTO [table] (id, ...) VALUES (...); select scope_identity()
问题是:“以防万一,禁用所有表的implicit_returning
是否有害?”确实是,“使用SCOPE_IDENTITY()
而不是OUTPUT INSERTED
有什么缺点吗?”
我不是专家,但是我得到的印象是,尽管OUTPUT INSERTED
是当今的首选方法,但SCOPE_IDENTITY()
通常也可以。过去,SQL Server 2008(可能还有更早的版本?)存在一个错误,其中SCOPE_IDENTITY
有时未返回正确的值,但是我听说现在已被修复(see this question for more detail)。 (另一方面,@@IDENTITY
和IDENT_CURRENT()
之类的其他技术仍然很危险,因为它们在极端情况下可能会返回错误的值。有关更多详细信息,请参见同一页面上的this answer和其他技术)
OUTPUT INSERTED
仍然具有的最大优势是,它可以用于通过单个INSERT
语句插入多行的情况。您正在使用SQLAlchemy进行此操作吗?可能不是吧?所以没关系。
请注意,如果您将不得不对许多表禁用implicit_returning
,则可以通过为其进行混合来避免重复使用样板(以及希望所有表继承的其他列和属性) ):
class AutoincTriggerMixin():
__table_args__ = {
'implicit_returning': False
}
id = Column(Integer, primary_key=True, autoincrement=True)
class SomeModel(AutoincTriggerMixin, Base):
some_column = Column(String(1000))
...
有关更多详细信息,请参见this page in the SQLALchemy documentation。另外,它使哪些表涉及触发器更加明显。