2

昨日、あるプロジェクトに取り組んでいるときに、奇妙な 1 対 1 の関係を思いついたので、これをどのように実装するのが最善か (明らかに、私たちは間違っていました :D)

A と B の 2 種類のエンティティが存在するという考え方です。これらはそれぞれ独立して存在することもできますが、それらの間にリンクを持つこともできます。リンクがある場合、それは 1:1 リンクであり、双方向で機能する必要があります。

ボトルとキャップのようなものです。それらは別々に存在できますが、一緒に結合すると、ボトルのキャップは 1 つだけになり、キャップは 1 つの (同じ) ボトルだけに取り付けられます。

正規化、データの整合性などに関するすべてのベスト プラクティスを念頭に置きながら、この関係をどのように実装しますか?

追加:言い忘れていましたが、それぞれに十数個のプロパティがあるため、フィールドの半分が NULL の同じテーブルにそれらを配置するのは、かなり厄介な解決策です。また、リンクはいつでも切断され、別のエンティティで再作成される可能性があります。

4

9 に答える 9

7

これを解決するには、標準的な多対多の関係レイアウトから始めます。

TableA
  AId
  AInfo

TableB
  BId
  BInfo

TableA2B
  AId
  BId

次に、トリガー、一意のインデックス、制約を使用して、テーブルに 1:1 の関係を適用します。正確な方法は、システムのニーズによって異なります。

私がこの形式を気に入っている理由は、多くのリレーションシップが、エンティティーの一部ではないリレーションシップの一部として属性を持っているからです。このパターンは、現在も将来もそれを可能にします。

例:ある人が会社で働いています。関係には、個人エンティティまたは会社エンティティに適合しない雇用日があります。

于 2009-11-13T13:07:15.907 に答える
2
CREATE TABLE A (id INT NOT NULL PRIMARY KEY, field1, …)

CREATE TABLE B (id INT NOT NULL PRIMARY KEY, field1, …)

CREATE TABLE AB (aid INT NOT NULL, bid INT NOT NULL,
                CONSTRAINT pk_ab PRIMARY KEY (aid, bid),
                CONSTRAINT ux_a UNIQUE (aid), 
                CONSTRAINT ux_b UNIQUE (bid),
                CONSTRAINT fk_aid_a FOREIGN KEY (aid) REFERENCES A,
                CONSTRAINT fk_bid_b FOREIGN KEY (bid) REFERENCES B
                )
于 2009-11-13T16:34:34.757 に答える
2

スキーマは次のようになると思います。

create table A (
    A_id    integer    primary key,
    ...
);

create table B (
    B_id    integer    primary key,
    A_id    integer    references A (A_id),
    ...
);

alter table B add constraint c1 unique(A_id);

B は A の 1 つの行のみを参照でき、フィールドは一意であるため、A は B の 1 つの行によってのみ参照できます。

B.A_id は null 許容であるため、互いに参照しない行が A と B に存在する可能性があります。

一意の制約は、複数の NULL レコードの存在を排除しません。一意の制約は、値がすべて一意または NULL であることを保証します。

于 2009-11-13T13:07:53.907 に答える
0

考慮すべき IMO の 2 つの異なるケースがあります。ケース 1 は、一夫一婦制の結婚で最もよく描かれています。2 つのオブジェクトは独立して作成され、ある時点で結合されます。後で、それらは分離され、他のオブジェクトと結合される可能性があります。このような関係については、ここで他の多くの人が使用する A2B テーブル アプローチを提案します。

ケース 2 は双子で描かれています。2 つのオブジェクトが接続されている場合、それらは生まれたときから接続されており、一方が死ぬまで接続されています。その場合、作成時に両方に同じ主キーを与えることを選択できます (たとえば、Oracle では、シーケンスから 1 つの値を選択し、それを両方のテーブルの ID として使用します)。

于 2009-11-13T16:53:22.720 に答える
0

「両端に外部キーがあります。リンクを確立/切断しようとするときも厄介です。トリガーなどに頼らなければなりません。もっとエレガントな武器を望んでいました。」

SQL ベースのシステムの世界では、このような洗練された武器は見つかりません。

Darryl Peterson の回答は、論理的に正しい解決策を示しています。しかし、「複数代入」という TTM の概念がサポートされていないため、SQL では「リンクを変更する」というケースが悪夢になることがあります。

于 2009-11-13T23:33:24.793 に答える
0

ダリルが提案したソリューションを使用します。

TableA
  AId
  AInfo

TableB
  BId
  BInfo

TableA2B
  AId
  BId

次に、tableA2B の AId と tableA2B の BId に一意の制約を追加します。

alter TableA2B add constraint ucAId unique(AId)
alter TableA2B add constraint ucBId unique(BId)

それがあなたの問題を解決すると思います

tableB エントリにリンクされていない tableA エントリは、tableA にリンクされていない tableB エントリと同様に、TableA2B には存在しません。

制約により、tableA から tableB へ、または tableB から tableA への最大 1 つのリンクが強制されます。

于 2009-11-13T16:24:15.890 に答える
0

これに関する Tony Rogerson によるすばらしいブログ投稿があります: How to Create a One-to-One Relationship in SQL Server using DRI, Triggers and Views

于 2011-03-18T19:06:56.783 に答える
0

依存する一方または両方の端で一意の制約を持つ null 許容外部キー (両端で興味深い!)

于 2009-11-13T13:02:23.237 に答える
0

A を参照する外部キーと B を参照する外部キーの結合テーブルを分離し、両方の列に UNIQUE 制約を設定します。したがって、2 つのエンティティ間のリンクが存在し、それがいずれかの唯一のリンクであるか、リンクが存在しないためテーブルに行がありません。

于 2009-11-13T13:27:03.433 に答える