sql >> データベース >  >> RDS >> Sqlserver

データベースで継承をどのように表すことができますか?

    @Bill Karwinは、SQL Entity-Attribute-Valueアンチパターンのソリューションを提案する際に、SQLアンチパターンの本で3つの継承モデルについて説明しています。これは簡単な概要です:

    単一テーブル継承(別名、階層ごとの継承):

    最初のオプションのように単一のテーブルを使用するのが、おそらく最も単純な設計です。おっしゃるように、サブタイプ固有の多くの属性にはNULLを指定する必要があります これらの属性が適用されない行の値。このモデルでは、次のような1つのポリシーテーブルがあります。

    +------+---------------------+----------+----------------+------------------+
    | id   | date_issued         | type     | vehicle_reg_no | property_address |
    +------+---------------------+----------+----------------+------------------+
    |    1 | 2010-08-20 12:00:00 | MOTOR    | 01-A-04004     | NULL             |
    |    2 | 2010-08-20 13:00:00 | MOTOR    | 02-B-01010     | NULL             |
    |    3 | 2010-08-20 14:00:00 | PROPERTY | NULL           | Oxford Street    |
    |    4 | 2010-08-20 15:00:00 | MOTOR    | 03-C-02020     | NULL             |
    +------+---------------------+----------+----------------+------------------+
    
    \------ COMMON FIELDS -------/          \----- SUBTYPE SPECIFIC FIELDS -----/
    

    デザインをシンプルに保つことはプラスですが、このアプローチの主な問題は次のとおりです。

    • 新しいサブタイプを追加する場合は、これらの新しいオブジェクトを説明する属性に対応するようにテーブルを変更する必要があります。これは、多くのサブタイプがある場合、または定期的にサブタイプを追加する予定の場合、すぐに問題になる可能性があります。

    • どの属性がどのサブタイプに属するかを定義するメタデータがないため、データベースはどの属性が適用され、どの属性が適用されないかを強制できません。

    • NOT NULLを強制することもできません 必須である必要があるサブタイプの属性について。これはアプリケーションで処理する必要がありますが、一般的には理想的ではありません。

    具体的なテーブルの継承:

    継承に取り組む別のアプローチは、サブタイプごとに新しいテーブルを作成し、各テーブルのすべての共通属性を繰り返すことです。例:

    --// Table: policies_motor
    +------+---------------------+----------------+
    | id   | date_issued         | vehicle_reg_no |
    +------+---------------------+----------------+
    |    1 | 2010-08-20 12:00:00 | 01-A-04004     |
    |    2 | 2010-08-20 13:00:00 | 02-B-01010     |
    |    3 | 2010-08-20 15:00:00 | 03-C-02020     |
    +------+---------------------+----------------+
                              
    --// Table: policies_property    
    +------+---------------------+------------------+
    | id   | date_issued         | property_address |
    +------+---------------------+------------------+
    |    1 | 2010-08-20 14:00:00 | Oxford Street    |   
    +------+---------------------+------------------+
    

    この設計は、基本的に、単一テーブル方式で特定された問題を解決します。

    • 必須属性をNOT NULLで適用できるようになりました 。

    • 新しいサブタイプを追加するには、既存のテーブルに列を追加するのではなく、新しいテーブルを追加する必要があります。

    • vehicle_reg_noなどの特定のサブタイプに不適切な属性が設定されるリスクもありません。 プロパティポリシーのフィールド。

    • typeは必要ありません シングルテーブルメソッドのように属性。タイプはメタデータによって定義されます:テーブル名。

    ただし、このモデルにはいくつかの欠点もあります。

    • 共通の属性はサブタイプ固有の属性と混合されており、それらを識別する簡単な方法はありません。データベースも知りません。

    • テーブルを定義するときは、サブタイプテーブルごとに共通の属性を繰り返す必要があります。それは間違いなくドライではありません。

    • サブタイプに関係なくすべてのポリシーを検索することは困難になり、大量のUNIONが必要になります。 s。

    これは、タイプに関係なく、すべてのポリシーを照会する必要がある方法です。

    SELECT     date_issued, other_common_fields, 'MOTOR' AS type
    FROM       policies_motor
    UNION ALL
    SELECT     date_issued, other_common_fields, 'PROPERTY' AS type
    FROM       policies_property;
    

    新しいサブタイプを追加するには、上記のクエリを追加のUNION ALLで変更する必要があることに注意してください。 サブタイプごとに。この操作を忘れると、アプリケーションにバグが発生しやすくなります。

    クラステーブル継承(別名、タイプ継承ごとのテーブル):

    これは、@Davidが他の回答で言及している解決策です。基本クラス用に単一のテーブルを作成します。これには、すべての共通属性が含まれます。次に、サブタイプごとに特定のテーブルを作成します。その主キーは、ベーステーブルへの外部キーとしても機能します。例:

    CREATE TABLE policies (
       policy_id          int,
       date_issued        datetime,
    
       -- // other common attributes ...
    );
    
    CREATE TABLE policy_motor (
        policy_id         int,
        vehicle_reg_no    varchar(20),
    
       -- // other attributes specific to motor insurance ...
    
       FOREIGN KEY (policy_id) REFERENCES policies (policy_id)
    );
    
    CREATE TABLE policy_property (
        policy_id         int,
        property_address  varchar(20),
    
       -- // other attributes specific to property insurance ...
    
       FOREIGN KEY (policy_id) REFERENCES policies (policy_id)
    );
    

    このソリューションは、他の2つの設計で特定された問題を解決します。

    • 必須の属性は、NOT NULLで適用できます 。

    • 新しいサブタイプを追加するには、既存のテーブルに列を追加するのではなく、新しいテーブルを追加する必要があります。

    • 特定のサブタイプに不適切な属性が設定されるリスクはありません。

    • typeは必要ありません 属性。

    • これで、共通の属性がサブタイプ固有の属性と混合されなくなりました。

    • いよいよ乾いたままでいられます。テーブルを作成するときに、サブタイプテーブルごとに共通の属性を繰り返す必要はありません。

    • 自動インクリメントのidの管理 ポリシーは、各サブタイプテーブルが個別に生成するのではなく、ベーステーブルで処理できるため、より簡単になります。

    • サブタイプに関係なくすべてのポリシーを検索することが非常に簡単になりました。UNIONはありません s必要-SELECT * FROM policiesのみ 。

    ほとんどの状況で、クラステーブルアプローチが最も適していると思います。

    これら3つのモデルの名前は、MartinFowlerの著書Patternsof EnterpriseApplicationArchitectureに由来しています。



    1. 基本的なSQLクエリ

    2. @@ IDENTITY、SCOPE_IDENTITY()、OUTPUT、および最後のIDを取得するその他のメソッド

    3. テーブル式の基礎、パート9 –ビュー、派生テーブルおよびCTEとの比較

    4. NodeJSPostgresエラーgetaddrinfoENOTFOUND