外部キー列/曖昧性解消の制約
外部キー制約を参照していると仮定します 、簡単な答えはあなたはそれらを使用しないです 。
そして、ここに長いものがあります:
列が外部キーであるを参照することに慣れています。 他のテーブルに。特に正規化プロセスでは、 "user_purchase.i_id
のようなフレーズ items
への外部キーです テーブル」 非常に一般的です。これは関係を説明するための完全に有効な方法ですが、実装フェーズに達すると少しあいまいになる可能性があります。
なしでテーブルを作成したとします。 FOREIGN KEY
条項:
CREATE TABLE user(
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(20) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE items(
i_id INT(11) NOT NULL AUTO_INCREMENT,
name TINYTEXT NOT NULL,
price DECIMAL(8,2) NOT NULL,
PRIMARY KEY (i_id)
);
CREATE TABLE user_purchase(
i_id INT(11) NOT NULL,
name TINYTEXT NOT NULL,
id INT(11) NOT NULL,
);
関係的には、外部キーの列に注意してください。 まだ実装されています 。 user
を参照する列があります テーブル(id
)およびitems
を参照する別のアイテム テーブル(i_id
)-name
を入れましょう しばらく脇に置きます。次のデータを検討してください:
user user_purchase items
| id username | | id i_id | | i_id name price |
| 23 john | | 55 10 | | 10 chocolate bar 3.42 |
| 55 mary | | 70 10 | | 33 mobile phone 82.11 |
| 70 fred | | 70 33 | | 54 toothpaste 8.67 |
| 55 10 | | 26 toy car 6.00 |
| 70 26 |
関係はそこにあります。 user_purchase
を使用して実装されます 誰が何を購入したかに関する情報を保持するテーブル 。関連するレポートをデータベースに照会する場合は、次のようにします。
select * from user_purchase p
join user u on (p.id=u.id)
join items i on (p.i_id=i.i_id)
これが、リレーションと外部キーの列の使用方法です。 関与します。
さて、もし私たちがそうしたらどうなるでしょう:
insert into user_purchase (id,i_id) values (23,99)
どうやら、これは無効なエントリです。 id=23
のユーザーがいますが 、i_id=99
のアイテムはありません 。 RDBMSはそれを可能にします。なぜなら、それはそれ以上のことを知らないからです 。まだ。
ここで、外部キーが制約します。 場に出る。 FOREIGN KEY (i_id) REFERENCES items(i_id)
を指定する user_purchase
で テーブル定義では、基本的にRDBMSに従うルールを指定します。 i_id
のエントリ items.i_id
に含まれていない値 列は受け入れられません 。つまり、外部キー列 参照を実装します 、外部キー制約 参照整合性を適用します 。
ただし、上記のselect
FK制約を定義したからといって、変更されることはありません。したがって、あなた データを保護するために、RDBMSが使用するFK制約を使用しないでください。
冗長性
自問してみてください:なぜあなたはそれが欲しいのですか? 2つの外部キーが同じ目的を果たす場合、冗長性は最終的に問題を引き起こします。次のデータを検討してください:
user_purchase items
| id i_id name | | i_id name price |
| 55 10 chocolate bar | | 10 chocolate bar 3.42 |
| 70 10 chocolate bar | | 33 mobile phone 82.11 |
| 70 33 mobile phone | | 54 toothpaste 8.67 |
| 55 10 toothpaste | | 26 toy car 6.00 |
| 70 26 toy car |
この写真の何が問題になっていますか?ユーザー55
を実行しました 2つのチョコレートバー、またはチョコレートバーと歯磨き粉を購入しますか?この種のあいまいさは、データの同期を維持するための多大な労力につながる可能性があります。これは、外部キーの1つだけを保持する場合は不要です。実際、name
を削除してみませんか 関係によって暗示されるため、列全体。
もちろん、PRIMARY KEY(i_id,name)
を設定して、複合外部キーを実装することでこれを解決できます。 items
の場合 テーブル(または追加のUNIQUE(i_id,name)
を定義する インデックス、それは実際には重要ではありません)そしてFOREIGN KEY(i_id,name) REFERENCES items(i_id,name)
を設定します 。このように、items
に存在する(i_id、name)カップルのみ テーブルはuser_purchases
に対して有効です 。 まだ1つあるという事実は別として 外部キー 、i_id
であれば、このアプローチはまったく不要です。 列はすでにアイテムを識別するのに十分です(name
について同じことを言うことはできません 列...)。
ただし、テーブルに複数の外部キーを使用することに対する規則はありません。実際、そのようなアプローチを必要とする状況があります。 person(id,name)
について考えてみましょう。 テーブルとparent(person,father,mother)
1つは、次のデータを使用します:
person parent
| id name | | person father mother |
| 14 John | | 21 14 59 |
| 43 Jane | | 14 76 43 |
| 21 Mike |
| 76 Frank |
| 59 Mary |
明らかに、parent
の3つの列すべて テーブルはperson
への外部キーです 。 同じ関係ではありません 、ただし、3つの異なるものの場合 :人の親も人であるため、対応する2つの列は同じテーブルperson
を参照する必要があります します。ただし、3つのフィールドはだけではないことに注意してください。 だけでなく、する必要があります 別のperson
を参照する s同じparent
行、誰も彼自身の親ではなく、誰の父親も彼の母親ではないので。