外部キー制約
他のテーブルのデータを参照するようにカラムにつける制約
条件
参照される側(親)のcolumnは、主キーであるか、uniqueである必要がある
親と子の型は同一である必要がある
自己参照もできる
そのcolumn(子)を、他のtableのcolumn(親)を参照させる
親が削除または更新された時に、子も削除または更新を行うなどをできる
親を消した時に、子が存在しない値を見てバグる、ということを防ぐ
外部キー制約をかけておくことで、存在しない不当な値を登録させないように制御できる
例えば、users tableにuser_idが1~10までしか無い時に、外部キー制約を張っている別のtableのuser_id columnには11を入れられない
DBのtableからGraphQL Schemaを生成する時に楽できる
自動でrelationが張られる
これらは、例え外部キー制約がなくても、どのみちアプリケーション側で行うべき処理なので、制約としてあったほうが良いmrsekut.icon
参考
外部キー制約を使わないことの問題点
常にかけるべきか?
外部キー制約が問題になるケース
弱い整合性を保てば良いだけの時に、外部キー制約を使っている場合
DDDでいうAggregateが同じなら外部キー制約使うべき、そうじゃないなら使わないべきという主張
多用してはいけないらしい
なぜ?
「多用してはいけない」は主張としておかしい
「hogeという問題が起きうる」と言うべき
そのhogeが起きうるかどうかの判断を設計者に委ねればいい
「多用してはいけない」というとマジで使わないほうがいいのかなと誤解する
デメリット
親テーブルのレコード削除が一手間増える
設定を間違えた際に、意図せず重要なレコードが消える可能性がある
大量のデータを抱えた親レコードがあっても、外部キー制約があると分割して消すことが難しいため、削除の負荷を分散できない
強い整合性
作成・更新・削除する時に一緒に行う
弱い整合性
書き方
短く書くと
code:sql
CREATE TABLE orders (
order_id ...,
user_id int(11) unsigned NOT NULL -- ここのuser_idを、
REFERENCES users (user_id) -- users tableのuser_idと紐付かせる
ON DELETE RESTRICT -- delete時は、RESTRICT
ON UPDATE RESTRICT, -- update時は、RESTRICT
product_id ...,
PRIMARY KEY (order_id)
);
長く書くと
code:sql
CREATE TABLE orders (
order_id ...,
user_id int(11) unsigned NOT NULL,
CONSTRAINT fk_user_id
FOREIGN KEY (user_id)
REFERENCES users (user_id)
ON DELETE RESTRICT
ON UPDATE RESTRICT,
product_id ...,
PRIMARY KEY (order_id)
) ;
書かなくても自明じゃん