【发布时间】:2022-01-05 18:34:48
【问题描述】:
我有 4 个表,Person、Video、Alias,以及一个视频和人之间的关联表 video_person_association_table。
每个人都有别名。例如“Clark Kent”是一个人。他的一个别名是“超人”,另一个是“Kal-El”
A 人和他们的别名之间存在一对多关系,如下所示:
class Person(Base):
#... other class stuff
aliases: ["Alias"] = relationship("Alias", back_populates="person")
class Alias(Base):
#... other class stuff
person_id: int = Column(Integer, ForeignKey('person.id'))
person = relationship("Person", back_populates="aliases")
另外,一个人可以有很多视频,一个视频可以有很多人,所以视频和人的关系是多对多的:
class Person(Base):
#... other class stuff
videos: ["Video"] = relationship("Video", secondary=video_person_association_table, back_populates="people")
class Video(Base):
#... other class stuff
people: list["Person"] = relationship("Person", secondary=video_person_association_table, back_populates="videos")
video_person_association_table = Table("video_person_association_table",
Base.metadata,
Column('video_id', ForeignKey('video.id'), primary_key=True),
Column('person_id', ForeignKey('person.id'), primary_key=True)
)
这很好用。但是,我想在关联表中添加第三列,如下所示:
video_person_association_table = Table("video_person_association_table",
Base.metadata,
Column('video_id', ForeignKey('video.id'), primary_key=True),
Column('person_id', ForeignKey('person.id'), primary_key=True),
Column('alias_id', ForeignKey('alias.id'), primary_key=True)
)
我想这样做是因为我将人们与视频联系起来的方式是通过他们的别名。
例如,名为“这是一只鸟,这是一架飞机,不!是超人”的视频将与别名“超人”相关联。另一个视频“Kal-El the last son of Krypton”将关联 使用别名“Kal-El”
如果 Aliases 表如下所示:
| id | person_id | name |
|---|---|---|
| 1 | 1 | Clark Kent |
| 2 | 1 | Superman |
| 3 | 1 | Kal-El |
People 表如下所示: |编号 |生日| |:----:|:------:| | 1 | 1938|
视频表如下所示:
| id | title |
|---|---|
| 1 | It's a bird, it's a plane, No! It's Superman |
| 2 | Kal-El the last son of Krypton |
| 3 | Clark Kent receives an award for excellence in journalism |
我希望关联表如下所示:
| video_id | person_id | alias_id |
|---|---|---|
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
我想要这样的原因是,我想保留某个视频为何与某个人相关联的信息。所以为此我想存储我用来做关联的别名的id。
我还需要那里的人员 ID 以使查询更简单。如果人员 ID 不存在并且我想查看哪些人与某个视频相关联,我需要将视频加入别名,然后将别名加入人员。
这个问题是当我尝试运行 SqlAlchemy 并在这个表中插入一些东西时,我得到:
sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) NOT NULL constraint failed: video_person_association_table.alias_id
[SQL: INSERT INTO video_person_association_table (video_id, person_id) VALUES (?, ?)]
[parameters: ((1, 1), (1, 2))]
这里的问题不在于 NOT NULL 约束。它只是尝试将两个值插入关联表。有没有办法配置关系,使其使用 3 列而不是 2 列?
我知道有一个Association Object 但它适用于更复杂的场景,您需要在关联表上存储除外键之外的额外信息。但我只需要外键。
【问题讨论】:
-
我可能会给出周期性问题和重复关系。您不应该创建第三个表。而是在您要使用它时创建一个视图或进行连接。您在创建冗余表时走错了路。在它总是失败之前我已经尝试过类似的事情,因为这是对数据建模的错误方法。
-
@PeterMølgaardPallesen “你不应该创建第三个表。”你是什么意思?第三个表是在两个表之间建立多对多关系的标准方法。无论如何,您对如何以正确的方式实现类似目标有更好的了解吗?
-
如果你想要 alias_id 组合 video_id 你应该作为 video_person_association_table 和 alias 表的连接。所以基本上保持只有两个主键的结构并加入
-
@PeterMølgaardPallesen 我发布了一个可能的解决方案,但我不确定它是否比您的建议更好。
-
感谢您的回访和有趣的建议。你需要一个(ondelete="CASCADE")吗?你可以添加一个没有别名的人吗?我认为最初的建议更简单,我认为从长远来看,只要加入,你就会遇到更少的问题。只是出于好奇,原始设置有什么困难?
标签: python sqlalchemy