【问题标题】:Creating partial unique index with sqlalchemy on Postgres在 Postgres 上使用 sqlalchemy 创建部分唯一索引
【发布时间】:2015-03-14 15:04:51
【问题描述】:

SQLAlchemy 支持创建partial indexes in postgresql

是否可以通过 SQLAlchemy 创建partial unique index

想象一个表格/模型:

class ScheduledPayment(Base):
     invoice_id = Column(Integer)
     is_canceled = Column(Boolean, default=False)

我想要一个唯一的索引,其中对于给定的发票只能有一个“有效”的 ScheduledPayment。

我可以在 postgres 中手动创建:

CREATE UNIQUE INDEX only_one_active_invoice on scheduled_payment 
     (invoice_id, is_canceled) where not is_canceled;

我想知道如何使用 SQLAlchemy 0.9 将其添加到我的 SQLAlchemy 模型中。

【问题讨论】:

    标签: python postgresql sqlalchemy postgresql-9.2


    【解决方案1】:
    class ScheduledPayment(Base):
        id = Column(Integer, primary_key=True)
        invoice_id = Column(Integer)
        is_canceled = Column(Boolean, default=False)
    
        __table_args__ = (
            Index('only_one_active_invoice', invoice_id, is_canceled,
                  unique=True,
                  postgresql_where=(~is_canceled)),
        )
    

    【讨论】:

    • 这个问题是对我自己的健全性检查。是否可以在不将 is_canceled 作为索引定义的一部分的情况下定义索引。来自postgres docs about partial indexes“强制满足索引谓词的行之间的唯一性,而不限制那些不满足的行”。所以,Index('only_one_active_invoice', invoice_id, unique=True, postgresql_where=~is_canceled) 在定义中只使用invoice_id 就足够了,因为我们只想考虑未取消的发票,对吧?
    【解决方案2】:

    如果有人停下来寻找使用可以选择为NULL 的列设置部分唯一约束,方法如下:

    __table_args__ = (
        db.Index(
            'uk_providers_name_category',
            'name', 'category',
            unique=True,
            postgresql_where=(user_id.is_(None))),
        db.Index(
            'uk_providers_name_category_user_id',
            'name', 'category', 'user_id',
            unique=True,
            postgresql_where=(user_id.isnot(None))),
    )
    

    其中user_id 是一个可以是NULL 的列,我希望在(name, category, user_id) 的所有三个列中强制执行唯一约束,而NULL 只是user_id 的允许值之一。

    【讨论】:

      【解决方案3】:

      为了补充 sas 的答案,postgresql_where 似乎无法接受多个布尔值。因此,在您有两个可空列的情况下(让我们假设一个额外的“价格”列),不可能为 NULL/~NULL 的所有组合设置四个部分索引。

      一种解决方法是使用永远不会“有效”的默认值(例如,-1 表示价格或“”表示文本列。它们可以正确比较,因此最多允许一行具有这些默认值.

      显然,您还需要在所有现有数据行中插入此默认值(如果适用)。

      【讨论】:

        猜你喜欢
        • 2020-05-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多