やる気がストロングZERO

やる気のストロングスタイル

【テーブル設計】利便性のために余計なデータを持たせるのはアンチパターン

テーブルに見やすさや利便性などの為に余計なデータをもたせるのはアンチパターンだと思った。
アンチパターンというか、普通に駄目だと思う。

サンプルケース

以下のようなテーブルを使って社員情報を管理しているとする。
(会社テーブルを自己参照にすべきかは置いておく)

親会社テーブル

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。
いいデータ構造は、どうやっても間違ったデータを入れられない構造になっている。(と誰かが言ってた)