Bedingte Fremdschlüsselbeziehung

14

Ich habe derzeit einen Fremdschlüssel zwischen zwei Entitäten und möchte diese Beziehung von dem Entitätstyp einer der Tabellen abhängig machen. Hier ist die Hierarchie der Tabellen, dies erfolgt über FK-Aktualisierungen von Kind zu Eltern

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

Ich habe derzeit eine FK-Beziehung vom Mitarbeiter zum Geschäft

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

Ich möchte die Bedingung hinzufügen:

WHERE TransactionalStores.storeType != 'ONLINE_TYPE'

Ist dies möglich oder muss ich TransactionalStores in zwei neue Untertypen unterteilen (z. B. PhysicalStores und VirtualStores)?

As
quelle

Antworten:

17

Fremdschlüssel können bedingt werden ... irgendwie. Sie zeigen nicht das Layout jeder Tabelle an, daher sehen Sie hier ein typisches Design, das Ihre Beziehungen zeigt:

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 )
);

Die Onlines und BrickMorter hätten die gleiche Grundstruktur, wobei StoreType jedoch auf "O" oder "B" beschränkt wäre.

Jetzt möchten Sie einen Verweis von einer anderen Tabelle auf TransactionalStores (und damit auf die verschiedenen Speichertabellen), jedoch auf Kiosks und BrickMorter. Der einzige Unterschied wäre in der Einschränkung:

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 )
);

In dieser Tabelle erzwingt die FK-Referenz, dass StoreType entweder "K", "O" oder "B" ist, die Feldbeschränkung beschränkt sie jedoch weiter auf "K" oder "B".

Zur Veranschaulichung habe ich eine Check-Einschränkung verwendet, um die Speichertypen in der TransactionStores-Tabelle einzuschränken. Im wirklichen Leben wäre eine StoreTypes-Nachschlagetabelle mit StoreType als FK für diese Tabelle wahrscheinlich die bessere Wahl für das Design.

TommCatt
quelle
9

Ein Fremdschlüssel kann nicht von einer Bedingung abhängig gemacht werden, sodass dies nicht in Frage kommt. Die Geschäftsregel scheint zu sein, dass ein Mitarbeiter für ein und nur ein physisches Geschäft arbeiten kann. Angesichts dessen hat der Supertyp des Geschäfts zwei Untertypen, wie Sie vorgeschlagen haben: Physisch und Online . Jedes physische Geschäft kann von einem oder mehreren Mitarbeitern besetzt sein, und jeder Mitarbeiter muss einem und nur einem physischen Geschäft zugeordnet sein. In physischen Geschäften gibt es dann zwei Untertypen, Brick and Mortar und Kiosk . Mit drei direkten Untertypen - Kiosk , Online und Brick and Mortar- verbirgt eine Eigenschaft, die von jedem Geschäft besessen ist - ob es sich an einem physischen Ort befindet oder nicht. Jetzt muss ein Mensch die Semantik der Untertypnamen verstehen, um zu verstehen, dass in Online-Shops keine Mitarbeiter beschäftigt sind. Dies ist im deklarierten Schema nicht ohne weiteres ersichtlich, und Code in Form eines Triggers muss geschrieben werden, um dieses Verständnis in einer Weise auszudrücken, die das DBMS erzwingen kann. Das Entwickeln, Testen und Warten eines Triggers, der sich nicht auf die Leistung auswirkt, ist eine viel schwierigere Lösung, die im Buch Angewandte Mathematik für Datenbankexperten beschrieben wird .

Das Untertippen von Store zuerst nach seiner Art von Speicherort und dann nach der Art der Struktur des physischen Stores ist in Bezug auf die Geschäftsregeln korrekter und macht das Schreiben von Code zur Durchsetzung der Regel überflüssig. Sobald die Eigenschaft eindeutig als Geschäftsstandorttyp enthalten ist, der als Unterscheidungsmerkmal für die Untertypen verwendet werden kann, kann die Beziehung zwischen Mitarbeitern und physischen Geschäften direkt hergestellt werden und somit die Regel nur mit der Fremdschlüsseleinschränkung vollständig implementiert werden. Es handelt sich um ein mit Oracle SQL Developer Data Modeler erstelltes Datenmodell , das die Super- und Subtypisierung mit Barker-Ellis zeigtBox-in-Box-Notation für Super- und Subtypen, die ich wegen ihrer eleganten Darstellung bevorzuge. Das Diagramm kann nun auch die Regel übersichtlich darstellen.

Bildbeschreibung hier eingeben

Todd Everett
quelle