【问题标题】:sqlalchemy: create relations but without foreign key constraint in db?sqlalchemy:在数据库中创建关系但没有外键约束?
【发布时间】:2016-10-14 20:49:55
【问题描述】:

由于sqlalchemy.orm.relationship() 已经暗示了关系,我不想在 db 中创建约束。我该怎么办?

目前我在 alembic 迁移后手动删除这些约束。

【问题讨论】:

    标签: python orm sqlalchemy foreign-keys


    【解决方案1】:

    而不是定义“模式”级别ForeignKey 约束创建custom foreign condition;将您想用作“外键”的列和primaryjoin 传递给relationship。您必须手动定义primaryjoin,因为:

    默认情况下,该值是根据父子表(或关联表)的外键关系计算得出的。

    In [2]: class A(Base):
       ...:     a_id = Column(Integer, primary_key=True)
       ...:     __tablename__ = 'a'
       ...:     
    
    In [3]: class C(Base):
       ...:     c_id = Column(Integer, primary_key=True)
       ...:     a_id = Column(Integer)
       ...:     __tablename__ = 'c'
       ...:     a = relationship('A', foreign_keys=[a_id],
       ...:                      primaryjoin='A.a_id == C.a_id')
       ...:     
    

    也可以使用foreign()primaryjoin 中内联注释外键:

    a = relationship('A', primaryjoin='foreign(C.a_id) == A.a_id')
    

    您可以验证没有为表 c 发出FOREIGN KEY 约束:

    In [4]: from sqlalchemy.schema import CreateTable
    
    In [5]: print(CreateTable(A.__table__))
    
    CREATE TABLE a (
            a_id INTEGER NOT NULL, 
            PRIMARY KEY (a_id)
    )
    
    
    
    In [6]: print(CreateTable(C.__table__))
    
    CREATE TABLE c (
            c_id INTEGER NOT NULL, 
            a_id INTEGER, 
            PRIMARY KEY (c_id)
    )
    

    警告:

    请注意,如果没有在 DB 端设置 FOREIGN KEY 约束,您可以按照您想要的任何方式将您的引​​用完整性分解成碎片。在 ORM/应用程序级别存在关系,但无法在 DB 中强制执行。

    【讨论】:

    • 注意:关键是,C类的a_id上没有外键声明。关系参数似乎不影响模式,只影响python中的用法。
    • 是的,relationship 是一个 ORM 概念,有助于将 SQL 表关系映射到对象世界,但它没有定义它们。
    • 这也是处理外键规则将A.a_id 绑定到C.a_id (a_id = Column(Integer, ForeignKey('C.a_id'), primary_key=True)) 的正确方法吗?
    • A ForeignKey 在 DB 模式中定义了一个约束。外键约束有助于维护完整性;它可以防止您插入 a_idA 中不存在的 C,并且还可以定义在更改 A 时应该发生的级联操作 - 通常被删除。另一方面,relationship 定义了对象的关联方式。它可以并且经常确实使用 DB 模式外键约束信息来确定键列是什么,但正如这里所见,它并不是严格要求的。 relationship 还提供了定义 Python 中应该发生的事情的级联行为。
    • ...您可以定义 relationship 属性,例如在 ORM 的对象端仅列出过去的事件等。一个简单的外键约束本身并不能建模,它只是强制执行键完整性。
    猜你喜欢
    • 2021-07-10
    • 2020-09-16
    • 2011-10-29
    • 2018-03-05
    • 2013-03-01
    • 2011-08-30
    • 1970-01-01
    • 2011-04-30
    • 2020-03-17
    相关资源
    最近更新 更多