在Postgres上使用sqlalchemy创建部分唯一索引

时间:2015-01-16 03:05:36

标签: python postgresql sqlalchemy postgresql-9.2

SQLAlchemy支持创建partial indexes in postgresql

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

想象一下表/模型:

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

我喜欢一个独特的索引,其中只有一个"活跃"特定发票的预定付款。

我可以在postgres中手动创建:

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

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

3 个答案:

答案 0 :(得分:32)

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)),
    )

答案 1 :(得分:5)

如果有人因为设置了一个可选择为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

答案 2 :(得分:0)

要通过sas添加答案,postgresql_where似乎无法接受多个布尔值。因此,在您有两个无法使用的列的情况下(让我们假设一个额外的“价格”列),对于NULL / ~NULL的所有组合,不可能有四个部分索引。

一种解决方法是使用永远不会“有效”的默认值(例如,对于价格为-1或对于文本列为''。这些将正确比较,因此不允许多于一行具有这些默认值

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