SQLAlchemy 检查约束与连接

Mie*_*iek 4 python postgresql sqlalchemy python-3.x

我使用以下内容在 SQLAlchemy 中创建了多对多关系:

b_c = Table('b_c', 
            Column('b_id', UUIDType(binary=False), ForeignKey('b.id'), primary_key=True),
            Column('c_id', UUIDType(binary=False), ForeignKey('c.id'), primary_key=True)
           )
Run Code Online (Sandbox Code Playgroud)

其中cb是只有一id列 ( UUIDType(binary=false)) 的表以及与此类似的模型:

class A(object):
    __tablename__ = 'a'
    id = Column('id', UUIDType(binary=False), default=uuid.uuid4, primary_key=True)

class B(object):
    __tablename__ = 'b'
    id = Column('id', UUIDType(binary=False), default=uuid.uuid4, primary_key=True)
    a_id = Column(UUIDType(binary=False), ForeignKey('a.id'), nullable=False)
    a = relationship('A')

class C(object):
    __tablename__ = 'c'
    id = Column('id', UUIDType(binary=False), default=uuid.uuid4, primary_key=True)
    a_id = Column(UUIDType(binary=False), ForeignKey('a.id'), nullable=False)
    a = relationship('A')
Run Code Online (Sandbox Code Playgroud)

这种关系工作得非常好,我能够根据我的使用场景将 B 和 C 对象过滤到父 A。但是,为了确保超出使用这些模型的逻辑的数据的完整性,是否有任何最佳实践要求对于任何关系b_c, b.amust equal c.a

抱歉,如果这是其他答案,但我发现的任何示例都是针对表本身值的简单 CHECK 约束,并且不需要连接表的值。

Hal*_*Ali 5

从文档:

目前,CHECK 表达式不能包含子查询,也不能引用当前行列以外的变量。可以引用系统列 tableoid,但不能引用任何其他系统列。

您所描述的内容无法通过检查约束完成,但可以在插入或更新之前通过 sql 触发器实现:

这是一个 postgresql 函数和触发器定义,用于检查引用表的a_id外键是否相等。

CREATE FUNCTION ckref_b_c() RETURNS trigger AS $ckref_b_c$
  DECLARE
  bid uuid;
  cid uuid;
  BEGIN
    select a_id INTO bid FROM b WHERE id = NEW.b_id;
    select a_id INTO cid FROM c WHERE id = NEW.c_id;
    IF bid != cid THEN 
        RAISE EXCEPTION 'associated records do not refer to same parent in `a`';
    END IF;
    RETURN NEW;
  END;
 $ckref_b_c$ LANGUAGE plpgsql;

CREATE TRIGGER ckref_b_c BEFORE INSERT OR UPDATE ON b_c
  FOR EACH ROW EXECUTE PROCEDURE ckref_b_c(); 
Run Code Online (Sandbox Code Playgroud)

创建表后,您可以通过 sqlalchemy 引擎执行这些查询。Sqlalchemy 也有一个事件系统,您可以使用它来自动发出这些查询。