web-dev-qa-db-ja.com

2つの多対多の関係を介してテーブルが別のテーブルを参照する場合のデータの不整合の禁止

以下のデータベース設計があります(=>によって外部キー制約が示されています)。

 Company [id] 
 CompanyRealm [id、company_id => Company.id]多くの
 
 Project [id、company_id => Company.id] 
 ProjectRealm [id、project_id => Project.id、company_realm_id => CompanyRealm.id]多くの

問題は、提供されたデータベース設計が一貫性のないデータを許可することです。例えば:

 Company1(id =1)
 Company2(id =2)
 CompanyRealm(id = 11、company_id =1)
 Project(id = 33、company_id =2)
 ProjectRealm(id = 44、project_id = 33、company_realm_id = 11)

Companyには多数のRealmsProjectCompanyに属している可能性があり、任意の数の会社のRealmsに関係する可能性があります)

ProjectRealmは2つの異なる会社を指します。

  • Company1(CompanyRealmを使用);そして
  • Company2(プロジェクト経由)。

私のDB設計に何か問題がありますか?
「はい」の場合-どの処方に違反していますか?
いいえの場合-不正なデータ挿入を防ぐ方法(制約を介して?例外付きでトリガー?)

6
kakabomba

あなたが正しい、設計は矛盾を許容します、あなたが正確に気づくもの。 ProjectRealmは、Projectを通じて会社を指し、CompanyRealmを通じて別の会社を指している場合があります。

これは珍しいことではなく、関係に三角形または「ひし形」の形状がある場合に表示されます。

Realm          Company
   \           /     \
    \         /       \
     \       /         \
    CompanyRealm     Project
             \         /
              \       /  
               \     /    
             ProjectRealm

これをDRI(宣言的参照整合性)で強制したい場合の一般的なソリューション。通常のUNIQUEFOREIGN KEY、およびCHECK制約を通じて-トリガーではなく、ProjectRealm REFERENCES CompanyRealmおよびProjectRealm REFERENCES Project外部キーに複合キーを使用します。

company_realm_idを2つの列(company_idrealm_id)に置き換え、2つの参照テーブルのそれぞれに複合UNIQUE制約を追加する(または、それらのPRIMARY KEYを変更する)必要があります。

Company [id]

Realm [id]

CompanyRealm [id, realm_id=>Realm.id, company_id=>Company.id,
              UNIQUE(company_id, realm_id)]

Project [id, company_id=>Company.id,
         UNIQUE(company_id, id)]

ProjectRealm [id, project_id, company_id, realm_id,
              (company_id, project_id) => Project (company_id, id),
              (company_id, realm_id) => CompanyRealm (company_id, realm_id)]

同じ(または非常に類似した)問題が発生する他のいくつかの質問も参照してください。ダイヤモンドパターンは、すべての点で明白です。

7
ypercubeᵀᴹ