【问题标题】:Do I need multiple association tables for this relationship?这种关系是否需要多个关联表?
【发布时间】:2012-02-05 16:25:46
【问题描述】:

我正在努力寻找构建将许多常量映射到许多项目的关系的最佳方法。

我最初的关系,一个项目有一个常量,看起来像这样。

class Constant(Base):
    __tablename__ = "Constant"
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(64), nullable=False)

class Item(Base):
    __tablename__ = "Item"
    id = Column(Integer, primary_key=True, autoincrement=True)
    constantId = Column(Integer, ForeignKey("Constant.id"))
    constant = relationship("Constant")

但是,我真的需要我的项目有多个常量,比如这样...

class Item(Base):
    __tablename__ = "Item"
    id = Column(Integer, primary_key=True, autoincrement=True)
    constant1Id = Column(Integer, ForeignKey("Constant.id"))
    constant1 = relationship("Constant")
    constant2Id = Column(Integer, ForeignKey("Constant.id"))
    constant2 = relationship("Constant")

我的第一次尝试是使用关联表...

item_to_constant_assoc = Table("itemToConstantAssoc", Base.metadata, Column("constantId", Integer, ForeignKey("Constant.id"), Column("itemId", Integer, ForeignKey("Item.id")))

同时更新 Item 类:

Class Item(Base):
__tablename__ = "Item"
id = Column(Integer, primary_key=True, autoincrement=True)
constant1 = relationship("Constant", secondary=item_to_constant_assoc, uselist=False)
constant2 = relationship("Constant", secondary=item_to_constant_assoc, uselist=False)

这失败了(在查看创建的 MySQL 表时可以理解),因为 Item.constant1 和 Item.constant2 引用了关联表中的相同条目。

我的下一步是为第二个常量添加另一个关联表,但我不得不怀疑我是否在寻找错误的树,因为我似乎正在为相对简单的映射创建大量表。我已经阅读了文档。它详细而充实(感谢 Michael Bayer!),我可能只是忽略了一部分。谁能给我一些关于这个问题的指针,或者我应该在文档中寻找什么?

谢谢! 菲尔

【问题讨论】:

  • 你的问题描述过于抽象。请更清楚地解释您要解决的问题,以便我们给出有意义的答案。
  • @TokenMacGuy 这对于我试图解决的实际问题可能没有你想象的那么抽象。我有一个视频编辑领域的常量表(例如,名为“FPS23976”的常量定义了 23.976 fps 的帧速率)。 Item 表定义了一个记录设备。这既有捕获率又有播放率,我想引用常量表。抱歉,如果我错误地陈述了问题。这不是我的专业领域。我的问题归结为:“多个关联表是构建这些关系的最佳方式吗?”
  • @PhilBoltt:请发布澄清作为问题的更新。不是评论。而是一流的更新,让问题是一个,一体化的整体。不是一堆有问题的想法加上 cmets。
  • 相机和帧率非常具体,比项目和常量更重要!
  • @TokenMacGuy 点了。感谢您的意见。

标签: python sqlalchemy associations relationship


【解决方案1】:

只见树木不见森林。这可以通过在关系上使用 primaryjoin 参数轻松完成。

class Item(Base):
    __tablename__ = "Item"
    id = Column(Integer, primary_key=True, autoincrement=True)
    constant1Id = Column(Integer, ForeignKey("Constant.id"))
    constant1 = relationship("Constant", primaryjoin="Constant.id==Item.constant1Id")
    constant2Id = Column(Integer, ForeignKey("Constant.id"))
    constant2 = relationship("Constant", primaryjoin="Constant.id==Item.constant2Id")

【讨论】:

    【解决方案2】:

    多对多关联已经允许每个项目拥有无限数量的常量。除了这两个基表之外,您不需要任何其他东西。

    class Constant(Base):
        __tablename__ = "Constant"
        id = Column(Integer, primary_key=True, autoincrement=True)
        name = Column(String(64), nullable=False)
    
    class Item(Base):
        __tablename__ = "Item"
        id = Column(Integer, primary_key=True, autoincrement=True)
        name = Column(String(64), nullable=False)    
    
    item_to_constant_assoc = Table("itemToConstantAssoc", Base.metadata, Column("constantId", Integer, ForeignKey("Constant.id"), Column("itemId", Integer, ForeignKey("Item.id")))
    

    此时,每个项目都有无限数量的常量。当你想要一个特定的常量时,你必须通过常量表中的名称属性来查询常量。您的关联表只是一个密钥对列表:(itemID, constantId)。

    一个项目的所有常量的集合是一个三表连接,用于与给定项目的匹配常量行连接的所有关联行。

    一个常量的所有项的集合是一个三表连接,用于所有关联行与给定常量的匹配项行连接。

    需要通过连接检索项目的特定常量。你可以把它想象成给定项目的所有常数的集合,其中项目和常数名称都给出了。即使只检索到一行,SQL 也涉及连接。

    我认为将常量与所有相关项或项与所有相关常量相关联的通用查询看起来像这样。

      query(Item). join(item_to_constant_assoc.itemId==Item.itemId). join(item_to_constant_assoc.contantId==Constant.constantId
    

    【讨论】:

    • 谢谢史蒂文。这确实让我更清楚关联表的作用。
    猜你喜欢
    • 2011-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多