SQLAlchemyは作成をサポートします postgresqlの部分インデックス 。
SQLAlchemyを介して partialuniqueindex を作成することは可能ですか?
テーブル/モデルを次のように想像してください。
class ScheduledPayment(Base):
invoice_id = Column(Integer)
is_canceled = Column(Boolean, default=False)
特定の請求書に対して「アクティブな」ScheduledPaymentが1つだけ存在できる一意のインデックスが必要です。
私はこれをpostgresで手動で作成できます:
CREATE UNIQUE INDEX only_one_active_invoice on scheduled_payment
(invoice_id, is_canceled) where not is_canceled;
SQLAlchemy0.9を使用してSQLAlchemyモデルにそれを追加するにはどうすればよいのでしょうか。
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)),
)
オプションで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
にすることができる列であり、NULL
が(name, category, user_id)
の許可値の1つであるuser_id
の3つの列すべてに一意の制約を適用したい。
Sasによる回答に追加するために、postgresql_whereは複数のブール値を受け入れることができないようです。したがって、NULL可能な列が2つある状況(追加の「価格」列を想定します)では、NULL/〜NULLのすべての組み合わせに対して4つの部分インデックスを持つことはできません。
回避策の1つは、「有効」になることのないデフォルト値を使用することです(たとえば、価格の場合は-1、テキスト列の場合は ''。これらは正しく比較されるため、これらのデフォルト値を持つことができるのは1行のみです。
もちろん、このデフォルト値を既存のすべてのデータ行に挿入する必要もあります(該当する場合)。