我在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)
)
c
和b
只有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')
这种关系完全正常,我可以根据我的使用场景将B和C对象过滤到父A。但是,为了确保数据的完整性超出使用这些模型的逻辑,是否有任何最佳实践要求对于任何关系b_c
,b.a
必须等于c.a
?
道歉,如果这个问题得到了回答,但是我发现的任何例子都是对表格本身的值的简单CHECK约束,没有任何要求连接表格的值。
答案 0 :(得分:3)
来自文档:
您所描述的内容不能通过检查约束来完成,但可以在插入或更新之前通过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();
创建表后,您可以通过sqlalchemy引擎执行这些查询。 Sqlalchemy还有一个事件系统,您可以使用它来自动发出这些查询。