web-dev-qa-db-ja.com

主キーではない列への外部キー参照

私は知っています。外部キーは行を一意に識別し、したがって主キーを参照する必要があります。

ただし、私の例を考えてみましょう。4つの事前定義されたカテゴリーがあり、これらのカテゴリーの値のいくつかの組み合わせには、モジュールの階層があります。階層構造は、親モジュール列によって実装されます。

私のアプローチは、これらの列を持つ単一のテーブルに実装することです:

  • カテゴリー1(例:地域)
  • カテゴリ2(学校の種類など)
  • カテゴリー3(例:クラス)
  • カテゴリ4(例、件名)
  • モジュールのタイトル
  • 親モジュールのタイトル
  • すべてのカテゴリとモジュールタイトルで構成される主キー。

親モジュールのタイトルがモジュールのタイトル列を参照するようにしたいと思います。ここで、外部キーは主キー全体を参照する必要があるため、親カテゴリ1、親カテゴリ2、親カテゴリ3、親カテゴリ4のような列を挿入する必要があります。ただし、親モジュールは常に子モジュールと同じ値を持っています4つのカテゴリすべてのため、これらの列は冗長になります。

テーブル宣言に次のようなものを書くことができれば理想的です。

---架空のSQL! ---

create table modules (
  ...,
  module_title varchar(50),
  foreign key parent_module_title varchar(50) 
    references modules(module_title) where 
      modules.category1 = category1 and modules.category2 = category2 and 
      modules.category3 = category3 and modules.category4 = category4
  )

または次のようなもの:

---架空のSQL! ---

  ...
  parent_module_title varchar(50)
    check (exists 
    (select * from modules where modules.module_title = parent_module_title))
  ...

これらは両方とも架空のwishfulSQL(後者はcannot use subquery in check constraintをスローします)ですが、私の目的を達成する方法はありますか?それが重要であれば、私はPostgresを使用しています。

2
David

@ypercubeᵀᴹがコメントで簡単な回答を示しました。これはまさに私が必要とするものです。複数の列から複数の列への外部キーを指定することが可能です。

_(cat1, cat2, cat3, cat4, parent_module_title)_ that REFERENCES (cat1, cat2, cat3, cat4, module_title)からFKを取得できます。

0
David

まず階層についてのメモ。あなたが現在モジュールに使用しているtryingのテクニックはadjacency listと呼ばれます。 パス列挙ネストされたセットクロージャーテーブルのような、より適切なSQLテクニックをいくつか参照することをお勧めします。

ただし、この文には何か問題があるようです:

しかし、親モジュールは常に4つのカテゴリすべての子モジュールと同じ値を持っていますなので、これらの列は冗長になります。

これはせいぜい異常に聞こえますが、階層は次のようになります。

1        region/
1.1      region/school/
1.1.1    region/school/class/
1.1.1.1  region/school/class/subject/

ここで問題は外部キーに関するものではなく、SQLの階層の実装に関するものだと主張します。

問題を簡単にするために、プロジェクトでpath enumerationを試してみて、必要に応じて他の手法を検討することをお勧めします。

-- Module titled TITLE is categorized as CAT_PATH.
--
module {TITLE, CAT_PATH}
    PK {TITLE}

どこ CAT_PATH の一つであります:

  • region/
  • region/school/
  • region/school/class/
  • region/school/class/subject/

これにより、さまざまな問題や質問が発生する可能性がありますが、それらの方が解決しやすくなります。

1
Damir Sudarevic

問題は、データベース設計がまったく正規化されていないことです。 regionsubjectmoduleなどのいくつかのテーブルにデータを分割して、テーブルの各行がこれらのエンティティの1つを表すようにします。

そうすれば、エンティティ間の外部キー関係を簡単に確立できるため、参照整合性が保証されます。

0
Laurenz Albe