web-dev-qa-db-ja.com

条件付き外部キー関係

現在、2つのエンティティ間に外部キーがあり、その関係をテーブルの1つのentityTypeに条件付きにしたいと考えています。これがテーブルの階層ですこれは子から親へのFK参照を介して行われます

                  Store
            /                \
  Employees                    \
                             TransactionalStores
                            /       |         \
                     Kiosks         |          BrickMortars
                                 Onlines

現在、従業員から店舗へのFK関係があります

ALTER TABLE Employees ADD CONSTRAINT Employee_Store
            FOREIGN KEY (TransStoreId)
            REFERENCES TransactionalStores(StoreId)

条件を追加したいと思います:

WHERE TransactionalStores.storeType != 'ONLINE_TYPE'

これは可能ですか、それともTransactionalStoresを2つの新しいサブタイプ(PhysicalStoresとVirtualStoresなど)にサブクラス化する必要がありますか?

14
Ace

外部キーcan条件付きにする...ソート。各テーブルのレイアウトは表示しないため、ここに関係を示す一般的なデザインを示します。

create table TransactionalStores(
    ID        int   not null auto_increment,
    StoreType char  not null,
    ..., -- other data
    constraint CK_TransStoreType check( StoreType in( 'B', 'K', 'O' )),
    constraint PK_TransactionalStores primary key( ID ),
    constraint UQ_TransStoreTypes unique( ID, StoreType ) -- for FK references
);
create table Kiosks(
    ID         int   not null,
    StoreType  char  not null,
    ..., -- other Kiosk data
    constraint CK_KioskStoreType check( StoreType = 'K' ), -- kiosks only
    constraint PK_Kiosks primary key( ID, StoreType ),
    constraint FK_Kiosks_TransStores foreign key( ID, StoreType )
        references TransactionalStores( ID, StoreType )
);

OnlinesとBrickMortersの基本的な構造は同じですが、StoreTypeが「O」または「B」のみに制限されています。

ここで、別のテーブルからTransactionalStoresへの(そしてそれを介してさまざまなストアテーブルへの)参照が必要ですが、キオスクとBrickMorterに制限されています。唯一の違いは制約です。

create table Employees(
    ID         int       not null,
    StoreID    int,
    StoreType  char,
    ..., -- other Employee data
    constraint PK_Employees primary key( ID ),
    constraint CK_Employees_StoreType check( coalesce( StoreType, 'X' ) <> 'O' )), -- Online not allowed
    constraint FK_Employees_TransStores foreign key( StoreID, StoreType )
        references TransactionalStores( ID, StoreType )
);

この表では、FK参照はStoreTypeを「K」、「O」、または「B」のいずれかに強制しますが、フィールド制約はさらに「K」または「B」のみに制限します。

説明のために、チェック制約を使用してTransactionStoresテーブルのストアタイプを制限しました。実際には、StoreTypeがそのテーブルへのFKであるStoreTypesルックアップテーブルが、より優れた設計の選択となるでしょう。

18
TommCatt

外部キーは条件付きにすることができないため、問題外です。ビジネスルールでは、従業員は1つだけの物理ストアで働くことができるようです。それを前提として、ストアのスーパータイプには、PhysicalOnlineの2つのサブタイプがあります。各実店舗には1人以上の従業員が配置され、各従業員は1つだけの実店舗に割り当てられる必要があります。実店舗には、Brick and MortarKioskの2つのサブタイプがあります。 3つの直接サブタイプ-キオスクオンライン、およびレンガとモルタル-各店舗が所有するプロパティを非表示にします-物理的な場所にあるかどうかにかかわらず。現在、デザインは人間に依存して、サブタイプ名に固有のセマンティクスを理解して、オンラインストアに従業員がいないことを理解しています。これは宣言されたスキーマではすぐにはわかりません。また、DBMSが実行できる方法でその理解を表現するために、トリガーの形式でcodeを記述する必要があります。本 データベース専門家のための応用数学 に示されているように、パフォーマンスに影響を与えないトリガーの開発、テスト、および維持は、実装するのがはるかに難しいソリューションです。

最初にその場所の種類をStoreでサブタイプし、次に物理的な店舗の種類の構造をしてからをサブタイピングすると、をビジネスルールに追加し、ルールを適用するコードを記述する必要をなくします。プロパティが、サブタイプの判別子として使用できる店舗ロケーションタイプとして明確に含まれると、従業員と実店舗との間に直接関係が作成され、外部キー制約のみでルールを完全に実装できます。 ereは Oracle SQL Developer Data Modeler で作成されたデータモデルで、スーパータイプとサブタイプのボックス表記で Barker-Ellis ボックスを使用してスーパータイプとサブタイプを示します。エレガントなプレゼンテーションが好きです。これで、図にルールも明確に示すことができます。

enter image description here

9
Todd Everett