1 :風吹けば名無し:
【悲報】ワイ、MySQLのFOREIGN_KEYで無事死亡😭
2 :風吹けば名無し:
FOREIGN_KEYってなんなん?(´・ω・`)
3 :風吹けば名無し:
2
「よそ者キー」や
4 :風吹けば名無し:
3
よそ者とかいうパワーワードやめろ
5 :風吹けば名無し:
簡単に言うと
-
親テーブル:users
-
子テーブル:threads(users.id を参照)
みたいな「親子関係」をDBに約束させるルールやで
6 :風吹けば名無し:
FOREIGN_KEYってカタカナにするとフォーリンキー?
遊戯王カードかな?
7 :風吹けば名無し:
6
正解はフォーリン・キーや
異邦の鍵やぞ😎
8 :風吹けば名無し:
FOREIGN KEY制約つけとくと
「いないユーザーIDをthreadに突っ込もうとしたらエラーになる」
これがいちばんの役目や
9 :風吹けば名無し:
つまりなんや
「嘘つくなよチェック」ってことか?
10 :風吹けば名無し:
9
そうそれ
参照整合性とかいうカッコいい名前がついとる
11 :風吹けば名無し:
ワイ「user消したろ!」
MySQL「そのuser、threadsでまだ使われとるで。ダメ🙅」
これをやってくれるのがFOREIGN KEY
12 :風吹けば名無し:
FOREIGN_KEYって書いてるけど
SQLの文法的には FOREIGN KEY な
アンダーバーは制約名につけるやつや
13 :風吹けば名無し:
CONSTRAINT fk_thread_user FOREIGN KEY (user_id) REFERENCES users(id)
↑
これ見ただけで頭痛くなるんやが
14 :風吹けば名無し:
13
分解するとこうや
-
CONSTRAINT fk_thread_user
→ 制約の名前。好きにつけてええ。 -
FOREIGN KEY (user_id)
→ 「このテーブルの user_id は外部キーやで」 -
REFERENCES users(id)
→ 「users テーブルの id を参照するで」
これだけや
15 :風吹けば名無し:
14
思ったより優しい説明で草
サンガツ
16 :風吹けば名無し:
ON UPDATE CASCADE
ON DELETE CASCADE
←こいつらもだいたいFOREIGN KEYのオプションや
17 :風吹けば名無し:
16
カスケードってなんやねんラーメン屋か?
18 :風吹けば名無し:
17
カスケード=連鎖や
親を更新・削除したら、
子も連鎖して更新・削除されるモードや
19 :風吹けば名無し:
ON DELETE CASCADE
親ユーザー消したら、そのユーザーが立てたスレも全部消える
ON DELETE RESTRICT
スレが残ってる限り、親ユーザーを消させない
こんな感じ
20 :風吹けば名無し:
RESTRICTは「待て、それは消したらあかん」って止めてくるやつやな
21 :風吹けば名無し:
ワイ、何も考えずにON DELETE CASCADE付けて
テストでuser消したらpostsが全部消えて無事死亡
22 :風吹けば名無し:
21
それが「カスケード地獄」や
本番DBでやるとガチで泣くで
23 :風吹けば名無し:
FOREIGN KEYないと何があかんの?
アプリ側でチェックしたらええやん?
24 :風吹けば名無し:
23
-
アプリがバグったら終わり
-
別のツールから直接DBいじられたら終わり
-
将来、自分が仕様を忘れててもDBが守ってくれる
「未来の自分を信じるな、DBを信じろ」ってことや
25 :風吹けば名無し:
24
最後の一行、刺さるからやめろ
26 :風吹けば名無し:
FOREIGN KEY張っとくと
「ゴミデータ(親のいない子)」が発生しにくいのがデカい
27 :風吹けば名無し:
ゴミデータってなに?
28 :風吹けば名無し:
27
例えばthreadsに
user_id = 99999 ってレコードがあるのに
usersテーブルに id=99999 が存在しない状態
「孤児データ」とか言われる
FOREIGN KEYないとそういうのが量産される
29 :風吹けば名無し:
ORPHAN(孤児)データとか言うと
急に重くなるからやめろ
30 :風吹けば名無し:
でもFOREIGN KEYって
インデックスとかちゃんと貼らんとクソ重くなるんやろ?
31 :風吹けば名無し:
30
基本は
-
親側:参照される列にINDEX(主キーなら勝手についてる)
-
子側:FOREIGN KEY張る列にもINDEX
これやっときゃそんなに怖くないで
32 :風吹けば名無し:
なんでみんな fk_〇〇 みたいな名前つけるん?
33 :風吹けば名無し:
32
fk = foreign key の略や
fk_thread_user→ 「threadテーブルのuserへの外部キー」
って人間に分かりやすくするための記号やな
34 :風吹けば名無し:
MySQL「外部キー制約エラーです(1452)」
ワイ「😭」
35 :風吹けば名無し:
34
エラー1452あるある
Cannot add or update a child row: a foreign key constraint fails
→ 子に入れようとしてるIDが、親に存在してへん
36 :風吹けば名無し:
FOREIGN KEY後から追加しようとして
既にゴミデータがあると追加できなくてキレる
37 :風吹けば名無し:
36
そのための
-
データ掃除
-
一時的にNULL許可
-
もしくは問題ある行を削除
や
「過去の自分の罪」を精算してから外部キーを張るんやで
38 :風吹けば名無し:
じゃあ最初からFOREIGN KEY付けといた方がええんか?
39 :風吹けば名無し:
38
設計時点で付ける派がだいたいのベストプラクティスやな
後から付けるのはだいたい「後悔した未来の自分」がやってる
40 :風吹けば名無し:
ORMとか使ってると勝手にFOREIGN KEY張ってくれたりしない?
41 :風吹けば名無し:
40
ツールによる
マイグレーションで
foreignId('user_id')->constrained()
とか書くと勝手にやってくれるやつもある
42 :風吹けば名無し:
ワイ「とりあえず全部ON DELETE CASCADEでええか」
先輩「やめろ」
43 :風吹けば名無し:
42
現場では
-
基本:RESTRICT or NO ACTION
-
どうしても一緒に消したいとこだけCASCADE
みたいな運用が多いイメージ
44 :風吹けば名無し:
FOREIGN KEY多すぎると、テーブル分割とか設計の甘さがバレる説
45 :風吹けば名無し:
44
逆に何もFOREIGN KEYないと
「このDB、怖すぎん?」ってなるからバランスや
46 :風吹けば名無し:
結局のところ
FOREIGN KEY=「DBに書かせる人間関係図」
みたいなもんよな
47 :風吹けば名無し:
46
-
親:PRIMARY KEY
-
子:FOREIGN KEY
-
約束:REFERENCES
-
人間関係のルール:ON DELETE / ON UPDATE
こう覚えるとわかりやすい
48 :風吹けば名無し:
なんか恋愛ゲームみたいになってきたな
49 :風吹けば名無し:
48
「親に振られたら(DELETEされたら)
子も後を追う(CASCADE)」とか怖すぎるやろ
50 :風吹けば名無し:
このスレ見てFOREIGN KEYちょっとだけ分かった気がするわ
サンキューなんJDB部📝









