データベースの正規化の基礎

適用対象: Microsoft Office Access 2007Microsoft Office Access 2003

難易度: 低 シングル ユーザー コンピューターのユーザー インターフェイスに関する知識が必要です。

Microsoft Access 2000 については、次の資料を参照してください。
209534
Microsoft Access 95 または Microsoft Access 97 については、次の資料を参照してください。
100139

概要


この資料では、データベースの正規化の専門用語を初心者向けに説明します。 これらの専門用語の基礎を理解しておくと、リレーショナル データベースの設計について検討するときに役立ちます。
 

詳細情報


正規化の説明

正規化とは、データベース内のデータを構築する処理のことです。 正規化には、データを保護しながらデータベースをより柔軟にするよう設計された規則に従い、冗長性の除去および矛盾する従属関係を除去することによってテーブルを作成する作業、およびテーブル間のリレーションシップを確立する作業が含まれます。


冗長なデータがあると、ディスク領域が浪費され、保守上の問題点が生じます。 複数の場所に存在するデータの変更が必要な場合、すべての場所でそれらのデータがまったく同一になるように変更する必要があります。 顧客の住所を変更する際に、データが格納されているのが "顧客" テーブルのみで、データベース内の他のテーブルに存在しない場合、変更作業を簡単に行うことができます。

"矛盾する従属関係" とは何でしょうか。 特定の顧客の住所を探す場合に "顧客" テーブルを調べることは直感的にわかりますが、その顧客を担当している社員の給与を調べるために、"顧客" テーブルを参照するのは適切ではありません。 社員の給与は、社員に関連付けられているか社員に従属するため、"社員" テーブルに移動する必要があります。 しかし、矛盾する従属関係があると、データを見つけるパスが存在しないか破損していることになり、データの参照が困難になります。

データベースの正規化にはいくつかの規則があります。 それぞれの規則は "正規形" と呼ばれます。 最初の規則に従っているデータベースは "第 1 正規形" であるといわれます。 最初の 3 つの規則に従っているデータベースは "第 3 正規形" であると見なされます。 他のレベルの正規化も可能ですが、ほとんどのアプリケーションでは、第 3 正規形が最も高いレベルと見なされています。

多くの規則や規格がそうであるように、現実のシナリオは常に規則に完全に適合しているとは限りません。 一般的に、正規化を行うと追加テーブルが必要となるため、わずらわしいと感じる顧客もいます。 正規化の最初の 3 つの規則のいずれかに違反した設計をする場合、冗長データや矛盾する従属関係など、アプリケーションで発生する可能性のある問題点を考慮しておく必要があります。

以下は、正規化の例です。

第 1 正規形

  • 各テーブルで繰り返し現れるグループを除去します。
  • 関連するデータごとに 1 つのテーブルを作成します。
  • 関連するデータ セットを主キーで識別します。
類似したデータを格納するために、1 つのテーブルで複数のフィールドを使用しないようにします。 たとえば、在庫項目が 2 つの製造元から納入される場合、在庫レコードで "製造元コード 1" フィールドおよび "製造元コード 2" フィールドを使用して、その項目を追跡するケースを考えてみます。

3 つ目の製造元を追加するとどうなるでしょうか。 単にフィールドを追加しただけでは、プログラムとテーブルの変更が必要となり、製造元の数が動的に変化する場合にスムーズに対応することができません。 この場合は、すべての製造元の情報を別の "製造元" テーブルに格納し、項目番号キーを使用して在庫テーブルを 製造元テーブルにリンクするか、製造元コード キーを使用して製造元テーブルを在庫テーブルにリンクします。

第 2 正規形

  • 複数のレコードに該当する値のセットごとに 1 つのテーブルを作成します。
  • これらのテーブルを外部キーと関連付けます。
レコードが、テーブルの主キー (必要な場合は、複合キー) 以外に従属しないようにする必要があります。 たとえば、財務システムにおける顧客の住所を考えてみます。 住所は "顧客" テーブルで必要ですが、"受注"、"出荷"、"請求"、"売掛金"、および "回収" の各テーブルでも必要です。 これらすべてのテーブルに顧客の住所を個別のエントリとして格納するのではなく、"顧客" テーブルまたは個別の "住所" テーブルのいずれか 1 つに格納します。

第 3 正規形

  • キーに従属しないフィールドを除去します。
レコードに、キーの一部ではない値が含まれる場合、その値を別のテーブルに分離します。 一般的に、一連のフィールドの内容が、テーブル内の複数のレコードに適用されるときは、それらのフィールドを別のテーブルに配置することを検討します。

たとえば、"社員募集" テーブルに、志願者の大学の名前と住所が含まれているとします。 しかし、大学に募集要項を送付するには、大学の完全な一覧が必要です。 大学の情報が "志願者" テーブルに格納されている場合、現在志願者がいない大学の一覧を取得することができません。 この場合、別に "大学" テーブルを作成し、大学コード キーを使用して "志願者" テーブルにリンクします。

例外: 第 3 正規形を遵守することが理論上望ましくても、常に実用的とは限りません。 "顧客" テーブルで、起こり得る内部フィールドの従属関係をすべて除去するには、都市、郵便番号、顧客担当者、顧客クラス、および複数のレコードで重複する可能性があるその他すべての要因に対して個別にテーブルを作成する必要があります。 理論上、正規化は実践する価値があります。 しかし、小さいテーブルを数多く作成するとパフォーマンスが低下したり、開くことのできるファイルおよびメモリの容量を超える場合があります。


第 3 正規形は、頻繁に変更されるデータに対してのみ適用する方がより現実的です。 従属フィールドが残っている場合、それらのいずれかが変更されるときに、関連付けられたすべてのフィールドの確認がユーザーによって行われるようにアプリケーションを設計します。

その他の正規形

ボイスコッド正規形 (BCNF) とも呼ばれる第 4 正規形、および第 5 正規形が存在しますが、実用的な設計と見なされることはほとんどありません。 これらの規則を無視すると、完全なデータベース設計とはならないことがありますが、機能的には影響しません。

サンプル テーブルを正規化する

以下の手順は、架空の学生テーブルを正規化するプロセスの例です。
  1. 正規化されていないテーブル

    Student#AdvisorAdv-RoomClass1Class2Class3
    1022Jones412101-07143-01159-02
    4123Smith216201-01211-02214-01
  2. 第 1 正規形: 繰り返しグループの除去

    テーブルは、2 次元にする必要があります。 1 人の学生が複数のクラスを受講するため、これらのクラスは別のテーブルにまとめる必要があります。 上記のレコードで "Class1"、"Class2"、および "Class3" のフィールドに設計上の問題点があります。

    スプレッドシートでは、3 次元を頻繁に使用しますが、テーブルでは使用するべきではありません。 この問題は "一対多の関係" から検討することもできます。"一対多" の "一" の側と "多" の側の両方を同じテーブルに配置しないようにします。 次のように、繰り返しグループ (Class#) を除去し、別のテーブルを作成して第 1 正規形にします。

    Student#AdvisorAdv-RoomClass#
    1022Jones412101-07
    1022Jones412143-01
    1022Jones412159-02
    4123Smith216201-01
    4123Smith216211-02
    4123Smith216214-01
  3. 第 2 正規形: 冗長データの除去

    上記の表では、各 Student# 値に複数の Class# 値があることに注目します。 Class# は機能上、Student# (主キー) に従属していません。そのため、このリレーションシップは、第 2 正規形ではありません。

    第 2 正規形にまとめると、以下の 2 つのテーブルのようになります。

    学生テーブル

    Student#AdvisorAdv-Room
    1022Jones412
    4123Smith216


    受講登録テーブル

    Student#Class#
    1022101-07
    1022143-01
    1022159-02
    4123201-01
    4123211-02
    4123214-01
  4. 第 3 正規形: キーに従属しないデータの除去

    上記の例で、Adv-Room (教授の部屋番号) は機能上 Advisor (教授) 属性に従属しています。 この場合の解決法は、以下のように、その属性を "学生" テーブルから "教授" テーブルに移動することです。

    学生テーブル

    Student#Advisor
    1022Jones
    4123Smith


    教授テーブル

    NameRoomDept
    Jones41242
    Smith21642