singulars
というエンティティとrelationships
というエンティティがあるとします。
singulars
エンティティを構成するには、正確に2つのrelationships
が必要です。
pairの単数形は、relationships
の他の場所で、任意の順序で繰り返すことはできません。
これをモデル化する1つの方法は次のようになります。
+----------------+
|relationships | +----------+
+----------------+ |singulars |
|id | +----------+
|singular_id_1 <---------+id |
|singular_id_2 <---+ |attribute1|
|pair_description| |attribute2|
|pair_date | | |
| | +----------+
+----------------+
このパターンでは、relationships
のどちらの側にも存在する可能性があるかどうか、singulars
の両方の外部キーフィールドを確認する必要があります。順序は関係ありませんが、スキーマで定義されています...したがって、クエリはAND
/OR
グループとケースの数で終わります。
そのアプローチを拡張すると、singular_id_[n]
を両側で入れ替えて、すべてのペアのtwoレコードを保存できます。これにより、いくつかのクエリの複雑さが解決されますが、さらに複雑になり、実行不可能になります。
中間テーブルを使用することは、1つの解決策のように思われます。
+----------------+ +-----------------------+
|relationships | |singulars_relationships| +----------+
+----------------+ +-----------------------+ |singulars |
|id <-------+relationship_id | +----------+
|pair_description| |singular_id +-------->id |
|pair_date | | | |attribute1|
| | +-----------------------+ |attribute2|
+----------------+ | |
+----------+
したがって、レコードは次のようになる可能性があります。
+----------------------------------+
|relationships |
+----------------------------------+
|id pair_description pair_date |
+----------------------------------+
|1 Fizz buzz blitz 2022-02-20|
|2 Blitz buzz fizz 2022-02-22|
+----------------------------------+
+----------------------------------+
|singulars_relationships |
+----------------------------------+
|relationship_id singular_id |
+----------------------------------+
|1 1 |
|1 2 |
|2 3 |
|2 4 |
+----------------------------------+
+-----------------------------+
|singulars |
+-----------------------------+
|id attribute1 attribute2 |
+-----------------------------+
|1 Fizz Blitz |
|2 Buzz Foo |
|3 Bar World |
|4 Blorg Hello |
+-----------------------------+
そこで、singulars_relationships
はペアが定義される場所です。 singular_id
がそこに存在する場合は、すでにペアになっています。このパターンで発生する可能性のある1つの問題は、3つ以上のsingular_id
がrelationship_id
に関連付けられ、「正確にn」の制約が損なわれる可能性があることです。
このタイプのシナリオの公式用語はありますか?そして、他の理論と代替?
このタイプのシナリオの公式用語はありますか?
はい。これは 対称関係 です。また、ここでの「関係」は「リレーショナルデータベース」と同じ意味です。 RDBMSは、関係の格納を中心に設計されたデータベース管理システムです。ただし、RDBMSには対称関係を保存するためのネイティブの方法がありません。 (a、b)と(b、a)などの両方のタプルを別々の行として格納するか、または何らかの規則を使用して1つのタプルのみを格納する必要があります。一般的なアプローチは、FKにチェック制約を使用することです。
例えば
check (singular_id_1 < singular_id_2)
関係が 反反射 であると仮定します。
コメントを待ち望んでいるので、これを David's ソリューションの補足として追加します。質問は理論的な性質のものでしたが、それが実際の生活でどのように実装できるかを見るのは興味深いかもしれません。
いくつかの状況では、反射防止特性と対称特性が強すぎますが、それでも「一意性」特性を保持する必要があります。一般的なパターンの1つは、BEFORE TRIGGERS
ユーザーが対称プロパティを意識する必要なく、関係を対称にする:
CREATE TRIGGER trigger1
BEFORE INSERT ON t
REFERENCING NEW AS N
FOR EACH ROW
SET (N.a, N.b) = (LEAST(N.a, N.b), GREATEST(N.a, N.b));
テーブルのプロパティ:
CHECK(a<=b);
UNIQUE(a,b);
このテーマのバリエーションは、生成された列を使用することです
CREATE TABLE t
( a int not null
, b int not null
, least_a_b generated always as ( least(a,b) )
, greatest_a_b generated always as ( greatest(a,b))
, unique (least_a_b, greatest_a_b)
);
生成された列も非表示になる場合があります。
least_a_b generated always as ( least(a,b) ) IMPLICITLY HIDDEN
例はDb2からのものですが、他のベンダーにも同様の機能が存在するはずです。