Python 带联接的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和

我在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


如果这是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”来进行约束。我通常会尽量避免触发,但在这里似乎是合适的。谢谢你的帮助!