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部📝