相关文章推荐
坚强的馒头  ·  c ...·  1 年前    · 
心软的柿子  ·  Java ...·  1 年前    · 
踢足球的酸菜鱼  ·  html - ...·  1 年前    · 
怕考试的鼠标  ·  android - How is ...·  1 年前    · 

在SQLAlchemy + SQLite中的一个列上有多个外键关系的关联表

0 人关注

tldr; 在SQLAlchemy ORM Mapper类中 docs 提供了一个例子,说明如何在两个表之间创建关联表的多对多关系,像这样。

但是,我怎样才能创建一个有四个父表和一个子表的多对多关联?在下面的E/R图中, keyword solution pattern question 是父表, data_lineage_lookup 是关联表,而 data_lineage 是子表。

背景信息。 我的数据库中有三个表来组织数据线元数据。第一个表, data_lineage_lookup ,是一个关联表(多对多),其中的 id 列与其他四个表有外键关系。 question solution pattern ,和 keyword 。在 data_lineage_lookup 中, id 列的每个id都是唯一的。每个这样的 id 都与一个 data_lineage_id 配对。

替换代码15】是 data_lineage 表的外键,该表持有关于数据来源的元数据,以json文档的形式保存在 json_body 列。

此外, data_lineage 表中的每个json文档都有一个相应的 json_schema (多对一的关系,许多文档共享相同的 json模式 )

-- association table I would like to recreate
CREATE TABLE IF NOT EXISTS data_lineage_lookup (
    id TEXT NOT NULL, 
    data_lineage_id TEXT NOT NULL, 
        -- text id's of any kind can be used to look up data lineage
        FOREIGN KEY (id) REFERENCES question (id) ON DELETE CASCADE,
        FOREIGN KEY (id) REFERENCES solution (id) ON DELETE CASCADE,
        FOREIGN KEY (id) REFERENCES pattern  (id) ON DELETE CASCADE,
        FOREIGN KEY (id) REFERENCES keyword  (id) ON DELETE CASCADE,
        FOREIGN KEY (data_lineage_id) REFERENCES data_lineage  (id) ON DELETE CASCADE
CREATE TABLE IF NOT EXISTS data_lineage (
    id TEXT NOT NULL PRIMARY KEY DEFAULT (lower(hex(randomblob(4)))),
    json_schema_id INTEGER NOT NULL,
    json_body         TEXT NOT NULL,
    date_found_timestamp INTEGER NOT NULL,
        FOREIGN KEY (json_schema_id) REFERENCES json_schema (id) ON DELETE RESTRICT
CREATE TABLE IF NOT EXISTS json_schema (
    id TEXT NOT NULL PRIMARY KEY DEFAULT (lower(hex(randomblob(4)))),
    title                   TEXT NOT NULL,
    body                    TEXT NOT NULL,
    date_added_timestamp INTEGER NOT NULL

The question:根据有关文件ORM映射器类中的多对多关系下面的例子用来说明如何使用关联表和relationship()列来建立多对多的关系,但这里的关联表有两列--它所关联的每个表都有一列,所以relationship()的使用是直接的。

association_table = Table('association', Base.metadata,
    Column('left_id', ForeignKey('left.id')),
    Column('right_id', ForeignKey('right.id'))
class Parent(Base):
    __tablename__ = 'left'
    id = Column(Integer, primary_key=True)
    children = relationship("Child",
                    secondary=association_table)
class Child(Base):
    __tablename__ = 'right'
    id = Column(Integer, primary_key=True)

我已经在SQLAlchemy中声明了下面的映射器类,但我如何配置data_lineage_lookup.id列,使其作为一个单一的外键列,映射到4个不同的表。替换代码3】、solutionpatternkeyword,通过JsonSchema中的relationship()来实现。ORM Mapper类?

Document Metadata Schema @declarative_mixin class DocumentMetadata: id = Column(Text, nullable=False, primary_key=True, default=text('(lower(hex(randomblob(4))))'), server_default=text('(lower(hex(randomblob(4))))')) body = Column(JSON, nullable=False) # TODO: check datatype after loading data with `select typeof(col) from table;` date_added = Column(DATETIME, nullable=False) def __repr__(self): return f"<{self.__class__.__name__}{self.__dict__}>" @declared_attr def __tablename__(cls): return re.sub(r'(?<!^)(?=[A-Z])', '_', cls.__name__).lower() data_lineage_lookup = Table( 'data_lineage_lookup', Base.metadata, Column('id', ForeignKey('question.id', ondelete="CASCADE"), ForeignKey('solution.id', ondelete="CASCADE"), ForeignKey('pattern.id', ondelete="CASCADE"), ForeignKey('keyword.id', ondelete="CASCADE") Column('data_lineage_id', ForeignKey('data_lineage.id', ondelete="CASCADE")) class JsonSchema(Base, DocumentMetadata): title = Column(Text, nullable=False) class DataLineage(Base, DocumentMetadata): json_schema_id = Column(Text, ForeignKey('json_schema.id', ondelete='RESTRICT'), nullable=False)
python
sqlite
sqlalchemy
David
David
发布于 2022-05-21
1 个回答
David
David
发布于 2022-06-07
已采纳
0 人赞同

解决办法是简单地将 keyword question pattern solution 作为父表处理。ORM mapper类作为父表,而 data_lineage 则作为子表。ORM mapper像子表,所有这些表都共享同一个关联表, data_lineage_lookup

因此,关联表的代码看起来像这样。

data_lineage_lookup = Table(
    'data_lineage_lookup',
    Base.metadata,
    Column(
        'id',
        ForeignKey('question.id', ondelete="CASCADE"),
        ForeignKey('solution.id', ondelete="CASCADE"),
        ForeignKey('pattern.id', ondelete="CASCADE"),
        ForeignKey('keyword.id', ondelete="CASCADE"),
        nullable=False
    Column('data_lineage_id', ForeignKey('data_lineage.id', ondelete="CASCADE"), nullable=False)

而每个数据ORM映射器类应该有一个data_lineages属性,如下所示

class Keyword(Base, Document):
    patterns = relationship(
        'Pattern',
        secondary=keyword_lookup,
        back_populates='keywords'