将行从“父”转移到“子”而不创建重复项并且不知道所有“父”列

use*_*443 5 schema postgresql duplication inheritance

我想建立一个具有不同模式的数据库,这些模式对应于不同的数据输入系统。需要有一个“master”(管理)模式和一个“party”表,以及多个其他模式,它们有自己的“party”表,这些表继承了 master party 表的字段

这是结构的一个简化示例:

'家长'

CREATE TABLE master.parties
(
  party_key serial NOT NULL,
  name text,
  date_of_birth date,
  phone text,
  CONSTRAINT "PK_master_parties" PRIMARY KEY (party_key)
)
Run Code Online (Sandbox Code Playgroud)

'孩子'

CREATE TABLE corporate.parties
(
  corp_key integer,
  corp_role text
) INHERITS (master.parties)
Run Code Online (Sandbox Code Playgroud)

我希望能够删除添加到 master.parties 表中的一行,并将其插入到其他模式(即公司)中的任何party表中,而无需在主表中创建重复的行。

我在另一篇文章(/sf/ask/2065641371/)上找到的这个解决方案非常接近我正在寻找的为了:

WITH deleted AS (
  DELETE FROM ONLY master.parties 
  WHERE party_key = 1
  returning *
)
INSERT INTO corporate.parties (name, date_of_birth, phone, corp_key, corp_role)
SELECT name, date_of_birth, phone, 2, 'President'
from deleted;
Run Code Online (Sandbox Code Playgroud)

但是,在我看来,应该有更好的方法将“父”表中的一行添加到“子”表中,而不必删除“父”表中的现有行。

该解决方案还带来了另一个更严重的问题:如果对主模式中的参与方表进行了更改(例如添加了新列),我不想更新与子模式对应的所有数据输入系统。 -schemas 在每个 INSERT 语句中包含该新列。如果我在代码中遗漏了一个 INSERT 语句,或者如果无法立即更新其中一个数据输入系统,当我尝试更新时,我可能会丢失 master.parties 表的新列中的值将一行放入另一个模式的派对表中(因为它不包含在现有的 INSERT 语句中)。

基本上我所追求的是能够从“父”表向“子”表中添加一行,而不必知道“父”表中的所有列,也不必在“中”创建重复行父母的表。这可能吗?我应该重新考虑我的数据库设计吗?

非常感谢任何帮助或建议!

Eva*_*oll 0

没有人(或者说很少有人)像这样使用“表继承”。这是一个不成熟的 PostgreSQL 功能,用于向用户公开一些内部基础,但可能会让他们感到困惑。我强烈建议避免它。欲了解更多信息,请参阅,

在您的情况下,虽然您可以使用单表层次结构自引用层次结构

CREATE SCHEMA master;
CREATE TABLE master.entities
(
  entity_id       int  GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  parent_id       int  REFERENCES master.entities,
  entity_name     text,
  entity_data      jsonb
);

INSERT INTO master.entities VALUES
  ( 1, null, 'Master', null),
  ( 2, 1   , 'Corp'  , '{"date_of_birth":"2018-07-05"}');
Run Code Online (Sandbox Code Playgroud)

我希望能够删除添加到 master.partys 表中的行并将其插入其他模式(即公司)中的任何 party 表中,而无需在主表中创建重复行。

我不是 100% 确定你在这里的意思。本质上,关系不是元数据,而是数据。因此,您必须有一个重复的行才能在两个父项下拥有一个实体。如果您想最大程度地减少 JSONB 的重复,尽管您可以将其外包到另一个表 - 尽管我可能不会打扰它,除非您对两方如何管理 jsonb 中存储的数据有一个所需的答案。

查询上面的结构稍微复杂一些,但你会掌握它的窍门,你必须使用递归 CTE。下找到很多这样的例子,

WITH RECURSIVE t(id,parents,name, data) AS (
  SELECT entity_id, ARRAY[]::int[], entity_name, entity_data
  FROM master.entities
  WHERE parent_id IS NULL
  UNION ALL
    SELECT e.entity_id, parents||parent_id, e.entity_name, e.entity_data
    FROM t
    INNER JOIN master.entities AS e
      ON e.parent_id = t.id
)
TABLE t;

 id | parents |  name  |              data               
----+---------+--------+---------------------------------
  1 | {}      | Master | 
  2 | {1}     | Corp   | {"date_of_birth": "2018-07-05"}
(2 rows)
Run Code Online (Sandbox Code Playgroud)

请注意,此模式还允许 N 级关系(您可以在子项下创建几乎无限数量的子项 - 不需要额外的表)