web-dev-qa-db-ja.com

複製を作成せず、すべての「親」列を認識せずに「親」から「子」に行を転送する

さまざまなデータ入力システムに対応するさまざまなスキーマを使用してデータベースをセットアップしたい。 「パーティー」テーブルを持つ「マスター」(管理)スキーマと、マスターパーティーテーブルからフィールドを継承する独自の「パーティー」テーブルを持つ他の複数のスキーマが必要です。

次に、構造の簡単な例を示します。

'PARENT'

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)
)

'CHILD'

CREATE TABLE corporate.parties
(
  corp_key integer,
  corp_role text
) INHERITS (master.parties)

マスターテーブルに重複する行を作成せずに、master.partiesテーブルに追加された行を削除して、他のスキーマ(つまり、企業)の任意のパーティーテーブルに挿入できるようにしたいと考えています。

私が別の投稿で見つけたこの解決策( https://stackoverflow.com/questions/29509162/postgres-table-inheritance-move-from-parent-to-child-and-vice-versa )は、私が探しているものに非常に近い:

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;

ただし、「親」テーブルの既存の行を削除せずに、「親」テーブルから「子」テーブルに行を追加するより良い方法があるはずだと私には思われます。

このソリューションは、別のより深刻な問題も引き起こします。マスタースキーマのパーティーテーブルが変更された場合(たとえば、新しい列が追加された場合)、サブに対応するすべてのデータ入力システムを更新する必要はありません。 -schemasは、すべてのINSERTステートメントにその新しい列を含めます。コードでINSERTステートメントを見逃したり、データ入力システムの1つをすぐに更新できなかったりすると、master.partiesテーブルのその新しい列の値が失われる危険性があります。行を別のスキーマのパーティーテーブルに移動します(既存のINSERTステートメントには含まれていないため)。

基本的に私が求めているのは、必ずしも「親」テーブルのすべての列を知らなくても、「親」テーブルから「子」テーブルに行を追加する機能を持ち、「親のテーブル。これは可能ですか? DB設計を再検討する必要がありますか?

ヘルプや提案は大歓迎です!

5
user2437443

このように、「テーブル継承」を使用する人は誰もいません(またはごく少数)。これは中途半端な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"}');

マスターテーブルに重複する行を作成せずに、master.partiesテーブルに追加された行を削除して、他のスキーマ(つまり、企業)の任意のパーティーテーブルに挿入できるようにしたいと考えています。

ここで何を言っているのか100%わかりません。基本的に、関係はメタデータではなく、データです。したがって、2つの親の下に1つのエンティティを配置するには、行を複製する必要があります。 JSONBの重複を最小限にしたい場合は、別のテーブルにアウトソーシングすることもできますが、2つのパーティがjsonbに格納されたデータをどのように管理するかについて希望の答えがない限り、私はおそらくそれを気にしません。

上記の構造のクエリは少し複雑ですが、こつこつとなるため、再帰的なCTEを使用する必要があります。 hierarchy の下に、この例がたくさんあります。

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)

このスキーマはNレベルの関係も許可することに注意してください(子の下にほぼ無限の数の子を作成できます-追加のテーブルは必要ありません)。

0
Evan Carroll