私は知っています。外部キーは行を一意に識別し、したがって主キーを参照する必要があります。
ただし、私の例を考えてみましょう。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を使用しています。
@ypercubeᵀᴹがコメントで簡単な回答を示しました。これはまさに私が必要とするものです。複数の列から複数の列への外部キーを指定することが可能です。
_
(cat1, cat2, cat3, cat4, parent_module_title)
_ thatREFERENCES (cat1, cat2, cat3, cat4, module_title)
からFKを取得できます。
まず階層についてのメモ。あなたが現在モジュールに使用している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/
これにより、さまざまな問題や質問が発生する可能性がありますが、それらの方が解決しやすくなります。
問題は、データベース設計がまったく正規化されていないことです。 region
、subject
、module
などのいくつかのテーブルにデータを分割して、テーブルの各行がこれらのエンティティの1つを表すようにします。
そうすれば、エンティティ間の外部キー関係を簡単に確立できるため、参照整合性が保証されます。