SQL:建模模板继承

时间:2018-03-17 19:00:17

标签: sql database postgresql database-design relational-database

我想问一下是否有可能对模板化数据结构建模,必要时可以覆盖它。

假设我们有一个包含以下项目的列表:

模板列表

  • 第1项位置0
  • 第2项位置1
  • 项目3位置2
  • 第4项立场3

现在我想创建一个使用模板列表作为基础的列表,但修改了它的某些部分:

具体列表,基于模板列表

  • 项目1位置0 //从模板列表继承
  • 项目5位置1 //新建且仅在具体列表中可用
  • 项目4位置2 //从模板列表继承,但位置不同
  • 第3项位置3 //从模板列表继承,但位置不同

在此列表中,缺少模板列表中的项目2 不应该是结果列表的一部分。

是否可以在SQL中建模这些关系? (我们正在使用PostgreSQL)

1 个答案:

答案 0 :(得分:1)

可以做你想要的事情,但它不一定是一个好的解决方案或你需要的。您要求的内容看起来像元模型,但关系数据库是为一阶逻辑模型设计的,虽然SQL可以超越这一点,但通常最好不要过于抽象。

那就是说,这是一个例子。我假设列表项的标识是位置或基于插槽的。

CREATE TABLE template_list (
    template_list_id SERIAL NOT NULL,
    PRIMARY KEY (template_list_id)
);

CREATE TABLE template_list_items (
    template_list_id INTEGER NOT NULL,
    slot_number INTEGER NOT NULL,
    item_number INTEGER NOT NULL,
    PRIMARY KEY (template_list_id, slot_number),
    FOREIGN KEY (template_list_id) REFERENCES template_list (template_list_id)
);

CREATE TABLE concrete_list (
    concrete_list_id SERIAL NOT NULL,
    template_list_id INTEGER NOT NULL,
    FOREIGN KEY (template_list_id) REFERENCES template_list (template_list_id),
    UNIQUE (concrete_list_id, template_list_id)
);

CREATE TABLE concrete_list_items (
    concrete_list_id INTEGER NOT NULL,
    template_list_id INTEGER NOT NULL,
    slot_number INTEGER NOT NULL,
    item_number INTEGER NULL,
    PRIMARY KEY (concrete_list_id, slot_number),
    FOREIGN KEY (concrete_list_id, template_list_id) REFERENCES concrete_list (concrete_list_id, template_list_id),
    FOREIGN KEY (template_list_id, slot_number) REFERENCES template_list_items (template_list_id, slot_number)
);

现在,要获取具体列表中的项目,您将使用如下查询:

SELECT c.concrete_list_id, x.slot_number, x.item_number
FROM concrete_list c
LEFT JOIN (
  SELECT ci.concrete_list_id,
         COALESCE(ci.template_list_id, ti.template_list_id) AS template_list_id,
         COALESCE(ci.slot_number, ti.slot_number) AS slot_number,
         COALESCE(ci.item_number, ti.item_number) AS item_number
  FROM concrete_list_items AS ci
  FULL JOIN template_list_items AS ti ON ci.template_list_id = ti.template_list_id
                                     AND ci.slot_number = ti.slot_number
) x ON c.concrete_list_id = x.concrete_list_id OR c.template_list_id = x.template_list_id;

这是一个SQL fiddle用于演示。请注意,为了简化演示,我用整数和硬编码值替换了串行类型。