PostgreSQL中postgresql_where多条件使用及Null唯一约束规避
用
postgresql_where规避PostgreSQL唯一性约束中Null值的特殊处理 咱们都清楚,PostgreSQL里的唯一性约束(包括UNIQUE索引)对Null值的处理是严格遵循SQL标准的——所有Null值都会被视为彼此唯一。也就是说,哪怕多条Item记录的name+purpose+batch_id组合里包含Null,数据库也不会判定它们重复。这在很多业务场景下并不符合实际需求,比如我们希望不管字段是否为Null,只要name+purpose+batch_id的组合“逻辑上相同”(包括Null的情况)就不允许重复。
这时候就可以借助SQLAlchemy的postgresql_where参数来定制唯一性约束的生效条件,以此规避PostgreSQL对Null值的特殊处理。下面是一个典型的示例:我们要禁止任何Item记录拥有相同的name+purpose+batch_id组合(包括这些字段为Null的场景)。
from sqlalchemy import Column, Integer, String, ForeignKey from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.dialects.postgresql import UniqueConstraint Base = declarative_base() class Item(Base): __tablename__ = 'item' id = Column(Integer, primary_key=True) batch_id = Column(Integer, ForeignKey('batch.id')) group_id = Column(Integer, ForeignKey('group.id')) name = Column(String(50), nullable=False) purpose = Column(String(50)) # 允许为Null # 自定义唯一性约束:将Null视为普通值,限制组合唯一 __table_args__ = ( UniqueConstraint( 'name', 'purpose', 'batch_id', # 可根据业务灵活调整条件:示例为当name不为Null时,整个组合(含Null)必须唯一 postgresql_where=(name.isnot(None)) ), )
简单解释下这个约束的逻辑:
- 当
name字段不为Null时,不管purpose和batch_id是否为Null,name+purpose+batch_id的组合都必须唯一 - 你可以根据业务需求修改
postgresql_where里的条件,比如如果只希望在batch_id不为Null时生效约束,就把条件改成(batch_id.isnot(None))
内容的提问来源于stack exchange,提问作者Ng Oon-Ee
相关产品推荐
相关产品推荐

