単純な原子値の場合、主に複雑さの面で、この一般的な知恵に同意しない傾向があります。帽子を含むテーブルを考えてみましょう。「非正規化」の方法を実行できます。
CREATE TABLE Hat (
hat_id INT NOT NULL PRIMARY KEY,
brand VARCHAR(255) NOT NULL,
size INT NOT NULL,
color VARCHAR(30) NOT NULL /* color is a string, like "Red", "Blue" */
)
または、「カラー」テーブルを作成して、さらに正規化することもできます。
CREATE TABLE Color (
color_id INT NOT NULL PRIMARY KEY,
color_name VARCHAR(30) NOT NULL
)
CREATE TABLE Hat (
hat_id INT NOT NULL PRIMARY KEY,
brand VARCHAR(255) NOT NULL,
size INT NOT NULL,
color_id INT NOT NULL REFERENCES Color(color_id)
)
後者の最終結果は、次の代わりに、いくつかの複雑さを追加したことです。
SELECT * FROM Hat
あなたは今、言わなければなりません:
SELECT * FROM Hat H INNER JOIN Color C ON H.color_id = C.color_id
その余分な参加は大したことですか?いいえ - 実際、それはリレーショナル デザイン モデルの基礎です - 正規化により、データの不整合の可能性を防ぐことができます。しかし、このような状況はすべて少し複雑になります。正当な理由がない限り、なぜそうしているのかを尋ねる価値があります。考えられる「正当な理由」には、次のものが含まれると考えています。
- この属性に「ぶら下がっている」他の属性はありますか? たとえば、16 進数値が常に色名に依存するように、「色名」と「16 進数値」の両方をキャプチャしていますか? その場合、1 つの行に ("Red", "#FF0000") があり、別の行に ("Red", "#FF3333") があるという状況を防ぐために、別のカラー テーブルが必要になることは間違いありません。複数の相関属性は、エンティティを正規化する必要があることを示す最大のシグナルです。
- 可能な値のセットは頻繁に変更されますか? 正規化されたルックアップ テーブルを使用すると、単一の行を更新するだけなので、セットの要素に対する将来の変更が容易になります。ただし、頻度が低い場合は、代わりにメイン テーブルの多数の行を更新する必要があるステートメントをためらわないでください。データベースはそれが得意です。よくわからない場合は、速度テストを行ってください。
- 可能な値のセットは、ユーザーによって直接管理されますか? つまり、リスト内の要素を追加/削除/並べ替えできる画面はありますか? もしそうなら、明らかに別のテーブルが必要です。
- 個別の値のリストは、UI 要素に影響を与えますか? たとえば、「色」は UI のドロップリストですか? そうすれば、ドロップリストを表示する必要があるたびにテーブルで SELECT DISTINCT を実行するよりも、それを独自のテーブルに置くほうがよいでしょう。
それらのどれにも当てはまらない場合、正規化する別の (正当な) 理由を見つけるのは難しいでしょう。値が特定の (小さい) 正当な値のセットの 1 つであることを確認したいだけの場合は、値が特定のリストにある必要があることを示す CONSTRAINT を使用することをお勧めします。必要に応じて、後で別のテーブルにいつでも「アップグレード」できます。