我是否应该始终在SQLAlchemy中使用&_ 39; implicit_returning':False?

时间:2016-03-20 01:16:54

标签: python sql-server sqlalchemy

始终使用' implicit_returning'在SQLAlchemy中有错误的潜在缺陷?

我在处理定义了触发器的MSSQL表时遇到过多次问题,而且由于DB处于复制状态,所有表都有触发器,只能通过放置' implicit_returning&#来解决。 39;:表格中的假。

我现在不确定问题究竟是什么,它与自动增量字段有关,可能是因为我预取了自动增量值,所以我可以将它插入另一个表中。

如果我没有设置“hidden_​​returning”'当我尝试插入值时,表格为False我得到一个错误,说明当触发器存在或某事时我不能使用RETURNING语句。如果需要,我可以用c / p确切的文字。

那么如果我将table_args放在所有映射类中只是为了安全起见呢?

对我来说特别令人沮丧的是我用于开发的本地数据库&测试不在复制中,并且不需要该选项,但生产数据库是复制的,因此当我部署更改时,它们有时不起作用。 :)

1 个答案:

答案 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)。 (另一方面,@@IDENTITYIDENT_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。另外,它使哪些表涉及触发器更加明显。