【问题标题】:How to avoid SQLAlchemy IntegrityError on uniqueness constraint when swapping unique values交换唯一值时如何避免唯一性约束上的 SQLAlchemy IntegrityError
【发布时间】:2020-07-09 20:06:19
【问题描述】:

我有如下 SQLAlchemy 模型(从实际实现中抽象出来)

class Parent():
    id = Column(postgresql.UUID, primary_key=True)

class Child():
    id = Column(postgresql.UUID, primary_key=True)
    parent_id = (postgresql.UUID,sqlalchemy.ForeignKey(Parent.id), nullable=False, index=True)
    order = sa_schema.Column(postgresql.SMALLINT)

而且我对 parent_id 和 order 有唯一性约束,因此父级上的子级排序是唯一的。我想编写代码以允许对这些孩子进行重新排序,例如,如果我有孩子 A B C D E 并希望将孩子 B 的顺序从 2 更改为 4,我将 C 从 3 更改为 2,将 D 从 4 更改为 3 . 所有这一切都在工作,但是当我去提交事务时,我得到一个 IntegrityError 说明其中一个 order/parent_id 对已经存在(每次都是随机的)。我已经关闭了自动刷新,有人知道我怎么能做到这一点吗?示例代码(显然这只处理订单增加的情况):

    children_to_update = session.query(models.Child).filter(
        models.Child.parent_id == parent_id,
        models.Child.order <= new_order,
        models.Child.order > original_order,
    ).with_for_update(nowait=True).all()
    for child_to_update in children_to_update:
        child_to_update.order = child_to_update.order - 1
        session.add(child_to_update)

    original_child.order = new_order
    session.add(original_child)
    session.commit()

【问题讨论】:

    标签: python sql postgresql sqlalchemy


    【解决方案1】:

    要完成这项工作,您首先需要使您对 (parent_id, order) 的唯一约束可延迟。

    然后您需要通过发送set constraints &lt;constraint name|all&gt; deferred; 来推迟查询之前的约束

    将在commit 上自动检查延迟约束。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-08
      • 1970-01-01
      • 1970-01-01
      • 2016-07-30
      • 2020-03-27
      • 1970-01-01
      • 1970-01-01
      • 2016-08-22
      相关资源
      最近更新 更多