Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating partial unique index with sqlalchemy on Postgres

SQLAlchemy supports creating partial indexes in postgresql.

Is it possible to create a partial unique index through SQLAlchemy?

Imagine a table/model as so:

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

I'd like a unique index where there can be only one "active" ScheduledPayment for a given invoice.

I can create this manually in postgres:

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

I'm wondering how I can add that to my SQLAlchemy model using SQLAlchemy 0.9.

like image 598
brianz Avatar asked Jan 16 '15 03:01

brianz


People also ask

Does Postgres create index on unique?

PostgreSQL automatically creates a unique index when a unique constraint or primary key is defined for a table. The index covers the columns that make up the primary key or unique constraint (a multicolumn index, if appropriate), and is the mechanism that enforces the constraint.

What is a partial unique index?

A partial index is an index built over a subset of a table; the subset is defined by a conditional expression (called the predicate of the partial index). The index contains entries for only those table rows that satisfy the predicate. Partial indexes are great when you need to filter a specific subset of data.

How do I change unique index in PostgreSQL?

There is no way to change an index to unique index. You can see what you can change to index at alter index document. In this case you need to drop and create new unique index.

Does unique constraint create index?

Yes, absolutely. A unique constraint creates a unique index.


Video Answer


2 Answers

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)),     ) 
like image 71
van Avatar answered Sep 17 '22 16:09

van


In case someone stops by looking to set up a partial unique constraint with a column that can optionally be NULL, here's how:

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

where user_id is a column that can be NULL and I want a unique constraint enforced across all three columns (name, category, user_id) with NULL just being one of the allowed values for user_id.

like image 28
sas Avatar answered Sep 16 '22 16:09

sas