如何为具有复合主键的表构建外键?

Posted

技术标签:

【中文标题】如何为具有复合主键的表构建外键?【英文标题】:How Can I Build a ForeignKey to a Table Which Has Composite Primary Key? 【发布时间】:2013-03-07 00:22:30 【问题描述】:

我在弄清楚如何为我正在定义的表正确构建我的 ForeignKey 列时遇到了很多麻烦。我在这里概述了我的模型(并在我的 PhoneNumber 模型中有问题的行旁边添加了注释):

class AreaCode(db.Model):
    __tablename__ = 'areacodes'
    area_code = db.Column(db.Integer, primary_key=True)
    exchanges = db.relationship('Exchanges', backref='area_code')


class Exchange(db.Model):
    __tablename__ = 'exchanges'
    exchange = db.Column(db.Integer, primary_key=True)
    area_code_pk = db.Column(db.Integer, db.ForeignKey('areacodes.area_code'), primary_key=True)


class PhoneNumber(db.Model):
    __tablename__ = 'phonenumbers'
    phone_number = db.Column(db.Numeric(precision=4, scale=0), primary_key=True)
    exchange_pk = db.Column(db.Integer, db.ForeignKey('exchanges.exchange'), primary_key=True) # this doesnt work since Exchange has two primary keys

这是发生了什么:

我的 Exchange 表有一个复合主键。这是我的用例所必需的。

我试图定义的 PhoneNumber 表需要 Exchange 表的 ForeignKey,但由于 Exchange 表有一个复合主键,我不知道如何使关系起作用。

任何指导将不胜感激。谢谢。

【问题讨论】:

在您的示例中,Exchange 只有一个主键? exchange 列是否也应为 primary=True 几个值得看的东西:docs.sqlalchemy.org/en/latest/core/…***.com/questions/10525797/… 还有,你用的是什么数据库? 嗨@shazow,你是对的,我在那里打错字了。 Exchange 有两个主键。另外,我使用的是 PostgreSQL 9.2。 你能解释一下“无法弄清楚如何让这种关系发挥作用”的意思吗?你试过什么?您是否在Relationship 中指定了foreign_keys?或者,您可以指定 primaryjoin 条件。 @rdegges:我已经编辑了关于术语的问题。 【参考方案1】:

因此,在与 sqlalchemy 邮件列表中的几位伟人交谈后,我终于解决了上述问题。下面是我的代码的最终版本,它允许我在表之间正确关联:

class AreaCode(db.Model):
    __tablename__ = 'areacodes'

    area_code = db.Column(db.Integer, primary_key=True)


class Exchange(db.Model):
    __tablename__ = 'exchanges'

    exchange = db.Column(db.Integer, primary_key=True)
    area_code_pk = db.Column(db.Integer, db.ForeignKey('areacodes.area_code'),
                             primary_key=True)
    area_code = db.relationship('AreaCode', backref=db.backref('exchanges', lazy='dynamic'))


class PhoneNumber(db.Model):
    __tablename__ = 'phonenumbers'
    __table_args__ = (
        db.ForeignKeyConstraint(
            ['exchange_exchange', 'exchange_area_code_pk'],
            ['exchanges.exchange', 'exchanges.area_code_pk'],
        ),
    )

    phone_number = db.Column(db.Integer, primary_key=True)
    exchange_exchange = db.Column(db.Integer, primary_key=True)
    exchange_area_code_pk = db.Column(db.Integer, primary_key=True)
    exchange = db.relationship('Exchange', backref=db.backref('phone_numbers', lazy='dynamic'))

【讨论】:

当您与 SQL Alchemy 人员聊天时,他们是否指定了为什么要在表上设置外键约束以及为什么不直接在 exchange_exchangeexchange_area_code_pk 两列上执行此操作? 不幸的是,@Carel,这是我大约 7 年前写的代码,老实说我不确定。我尝试通过我的收件箱进行搜索,但无法找到该线程——我怀疑它是在我现在无法访问的另一个电子邮件提供商上。对不起:( 感谢您付出了这么多努力@rdeggas,我真的很感激。我再次查看了 SQL Alchemy documentation,它指出这是在两个表之间设置复合外键的唯一方法。 Andrei Vacariu 现在也有一篇文章对此进行了深入探讨

以上是关于如何为具有复合主键的表构建外键?的主要内容,如果未能解决你的问题,请参考以下文章

具有主键和外键的事实表

mysql外键仅引用复合主键的一部分

创建具有主键和2个外键的表

休眠仅保存具有复合主键中的父外键的子表条目

主键和外键的复合键不能建立关系

使用 Spring-data-cassandra 查询具有复合主键的表