外部キー制約
参照整合性制約とも言う
他のテーブルのデータを参照するようにカラムにつける制約
SQLのREFERENCES句を使って指定する
外部キー制約のオプション
条件
参照される側(親)のcolumnは、主キーであるか、uniqueである必要がある
親と子の型は同一である必要がある
自己参照もできる
そのcolumn(子)を、他のtableのcolumn(親)を参照させる
親が削除または更新された時に、子も削除または更新を行うなどをできる
ref 外部キー制約のオプション
親を消した時に、子が存在しない値を見てバグる、ということを防ぐ
外部キー制約をかけておくことで、存在しない不当な値を登録させないように制御できる
例えば、users tableにuser_idが1~10までしか無い時に、外部キー制約を張っている別のtableのuser_id columnには11を入れられない
DBのtableからGraphQL Schemaを生成する時に楽できる
自動でrelationが張られる
これらは、例え外部キー制約がなくても、どのみちアプリケーション側で行うべき処理なので、制約としてあったほうが良いmrsekut.icon
参考
/mrsekut-book-477419087X/184 (外部キー制約でテーブル間の関係を明確にする)
/mrsekut-book-4873115892/082 (4章 キーレスエントリ(外部キー嫌い))
外部キー制約を使わないことの問題点
#WIP
常にかけるべきか?
外部キー制約が問題になるケース
https://blog.j5ik2o.me/entry/2020/06/16/105311
弱い整合性を保てば良いだけの時に、外部キー制約を使っている場合
DDDでいうAggregateが同じなら外部キー制約使うべき、そうじゃないなら使わないべきという主張
https://qiita.com/SLEAZOIDS/items/d6fb9c2d131c3fdd1387
https://xtech.nikkei.com/it/article/COLUMN/20090512/329851/
https://blog.j5ik2o.me/entry/2020/06/16/105311
https://tech.tabechoku.com/entry/2020/06/15/132518
https://kbigwheel.hateblo.jp/entry/2018/12/03/aggregate-and-consistency
https://naomichi-h.hatenablog.com/entry/2021/07/01/160457
https://ri.hateblo.jp/entry/2017/08/31/115328
https://hamamuratakuo.blog.fc2.com/blog-entry-1202.html
https://xtech.nikkei.com/it/article/COLUMN/20090512/329851/
多用してはいけないらしい
なぜ?
「多用してはいけない」は主張としておかしい
「hogeという問題が起きうる」と言うべき
そのhogeが起きうるかどうかの判断を設計者に委ねればいい
「多用してはいけない」というとマジで使わないほうがいいのかなと誤解する
デメリット
親テーブルのレコード削除が一手間増える
CASCADEにしたら避けられる
設定を間違えた際に、意図せず重要なレコードが消える可能性がある
大量のデータを抱えた親レコードがあっても、外部キー制約があると分割して消すことが難しいため、削除の負荷を分散できない
https://blog.j5ik2o.me/entry/2020/06/16/105311
トランザクション整合性
強い整合性
作成・更新・削除する時に一緒に行う
結果整合性
弱い整合性
書き方
SQLのREFERENCES句を使って指定する
短く書くと
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)
) ;
SQLのCONSTRAINT句は省略可能
FOREIGN KEY句も省略可能
逆になんでこれ必要なの #??
書かなくても自明じゃん