Python 带联接的SQLAlchemy检查约束
我在SQLAlchemy中创建了一个多对多关系,使用了如下内容:Python 带联接的SQLAlchemy检查约束,python,python-3.x,postgresql,sqlalchemy,Python,Python 3.x,Postgresql,Sqlalchemy,我在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_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
如果这是Elsehare回答的话,我很抱歉,但是我发现的任何示例都是针对表本身中的值的简单检查约束,并且不需要连接表的值。来自文档: 您所描述的内容不能通过检查约束完成,但可以在插入或更新之前通过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还有一个事件系统,您可以使用它自动发出这些查询。为什么
A
和C
子类对象
而不是模型
?感谢您指出这一点,在尝试删除一些不必要的细节时忽略了这一点-更新了问题我想您已经解决了。当我今天更深入地研究这个问题时,我肯定觉得我正在走一条非常丑陋的道路,试图用子查询执行检查。正如我发现的(你在回答中也提到了),这在postgres中是不允许的:这显然是合适的解决方案,因为我发现几乎没有人推荐函数“hack”来进行约束。我通常会尽量避免触发,但在这里似乎是合适的。谢谢你的帮助!