web-dev-qa-db-ja.com

独自の「IS-A」関係を実施する正しい方法は何ですか?

Personの関係があり、それとEmployee which IS-A PersonManager、which = ISA も。

ManagerEmployeeではないこと、およびその逆を確実にする正しい方法は何ですか?

質問をするときに何を探すべきかわかりませんでした。おそらく、その質問に対する答えはすでに存在しているでしょう。

Person (PK:personId, name, ...);
Manager(PK:#personId); -- A manager ISA person
Employee(PK:#personId); -- An employee ISA person

INSERT INTO Person (1,'Peter',...);
INSERT INTO Manager (1); -- OK
INSERT INTO Employee(1); -- Nope, error.

人は同時に従業員とマネージャーになることはできません。

多分別の例で。

Shape (shapeId);
Rectangle(shapeId, width, length);
Circle(shapeId, radius);

円は形状であり、長方形は形状です。長方形が円ではないことを確認するにはどうすればよいですか(またはその逆)。

したがって、私の質問、独自の「IS-A」関係を実施する正しい方法は何ですか?

ApplicationおよびPersonリレーションを参照するリレーションPositionは、一意のpersonID属性を持ち、単一の属性positionIDを持つ必要があります。一度に1つだけの値。

3
Kondybas

錯乱

ここに2つの別々の質問があり、これに答えることができません。

  • 人間関係(IS-A)について1つ質問があります。
  • 制約について1つの質問があります"マネージャーは従業員ではありません"

それらの1つはモデリングに関するもので、もう1つは整合性に関するものです。それは答えるのを難しくします

モデリング

RDBMSのスコープに(1:1)のIS-Aが表示される場合は常に、単純な外部キーを考える必要があります。

CREATE TABLE person (
   person_id  int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
   -- stuff
);

CREATE TABLE manager (
   manager_id  int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
   person_id   int REFERENCES person,
   -- stuff
);

CREATE TABLE employee (
   manager_id  int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
   person_id   int REFERENCES person
   -- stuff
);

多重継承(M2M)がある場合は、リンクテーブルを使用します。

誠実さ

"マネージャーは従業員ではなく、その逆も同様です"

これは、次のいずれかの場合にのみ実行できます

  • 関係は1つのテーブルに保存されます
  • データベースは、クエリをサポートするCHECK制約を実装します
  • TRIGGERを使用します

それがあなたの唯一の選択肢です。関係が1つのテーブルに格納されている場合。

CREATE TABLE relationships (
  id_person  REFERENCES person,
  id_manager REFERENCES manager,
  UNIQUE ( greatest(id_person,id_manager), least(id_person,id_manager) )
);

そして、それはうまくいくはずです。

その他の問題

これらの非常に単純なケースは、現実の世界では、たとえばn階層の関係など、より大きな問題に直面することがよくあります。マネージャーにマネージャーがいる場合はどうなりますか。それぞれに個別のテーブルを作成するプロセスは、非常に速くなります。

あなたはこれをすることができます、

CREATE TABLE persons (
  id_person     int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
  id_superior   REFERENCES persons
  ; stuff
);

ただし、この場合、id_personid_superiorがグラフに循環関係を作成しないようにする簡単な方法はないため、さらに賢くする必要があります...

そしてそれが、この種の質問がより多くの情報を必要とする理由です。

1
Evan Carroll