テーブルに見やすさや利便性などの為に余計なデータをもたせるのはアンチパターンだと思った。
※アンチパターンというか、普通に駄目だと思う。
サンプルケース
以下のようなテーブルを使って社員情報を管理しているとする。
(会社テーブルを自己参照にすべきかは置いておく)
親会社テーブル
id | 会社名 |
---|---|
1 | ノッてる株式会社 |
2 | ギリギリ株式会社 |
子会社テーブル
id | 会社名 | 親会社id |
---|---|---|
1 | ブラック株式会社 | 2 |
社員テーブル
id | 会社名 | 所属会社id |
---|---|---|
1 | 社畜 太郎 | 1 |
社畜 太郎さんは「ブラック株式会社」の社員である。
「ブラック株式会社」は「ギリギリ株式会社」の子会社である。
テーブル設計を見直して利便性UP
- 社員テーブルを見たときに親会社もすぐわかるようにしたい。
- 処理を書く時「社員->会社->親会社」と辿らないといけないのがめんどくさい。「社員->親会社」とすぐに参照できたほうが便利
のような要望により社員テーブルに親会社idカラムを追加した。
親会社テーブル
id | 会社名 |
---|---|
1 | ノッてる株式会社 |
2 | ギリギリ株式会社 |
子会社テーブル
id | 会社名 | 親会社id |
---|---|---|
1 | ブラック株式会社 | 2 |
社員テーブル
id | 会社名 | 所属会社id | 親会社id |
---|---|---|---|
1 | 社畜 太郎 | 1 | 2 |
これで社員テーブルをみれば、親会社もわかるし便利。
railsでも
parent_company = employee.parent_company
みたいにデータ取得できるので便利になった。
親会社が変わったら色々バグった
「ブラック株式会社」の親会社が「ギリギリ株式会社」から「ノッてる株式会社」に変わった。
なので、データを修正した。
親会社テーブル
id | 会社名 |
---|---|
1 | ノッてる株式会社 |
2 | ギリギリ株式会社 |
子会社テーブル(ブラック株式会社の親会社idを2 => 1に変更)
id | 会社名 | 親会社id |
---|---|---|
1 | ブラック株式会社 | 1 |
社員テーブル
id | 会社名 | 所属会社id | 親会社id |
---|---|---|---|
1 | 社畜 太郎 | 1 | 2 |
そして、社員テーブルの親会社idを返るのを忘れていた。
すると、社畜太郎さんは「ブラック株式会社」の社員だが、親会社を参照すると「ギリギリ株式会社」を参照してしまう。
社員=>子会社=>親会社と辿っていくと「ノッてる株式会社」となる。
データのとり方で親会社が変わってしまう。
データ不整合が起きた。
まとめ
テーブルには事実だけ保存し、利便性のためのデータを追加してはならない。(冗長なデータになるので)
「そういう構造になってるのだから、変えるのを忘れないようにする」というのはNG。
いいデータ構造は、どうやっても間違ったデータを入れられない構造になっている。(と誰かが言ってた)