J'ai actuellement une clé étrangère entre deux entités, et je voudrais rendre cette relation conditionnelle au type d'entité de l'une des tables. Voici la hiérarchie des tableaux, cela se fait via les réfractions FK de l'enfant au parent
Store
/ \
Employees \
TransactionalStores
/ | \
Kiosks | BrickMortars
Onlines
J'ai actuellement une relation FK de l'employé au magasin
ALTER TABLE Employees ADD CONSTRAINT Employee_Store
FOREIGN KEY (TransStoreId)
REFERENCES TransactionalStores(StoreId)
Je voudrais ajouter le conditionnel:
WHERE TransactionalStores.storeType != 'ONLINE_TYPE'
Est-ce possible ou dois-je sous-classer TransactionalStores en deux nouveaux sous-types (par exemple PhysicalStores et VirtualStores)
Les clés étrangères peuvent être conditionnées ... en quelque sorte. Vous ne montrez pas la disposition de chaque table, voici donc une conception typique montrant vos relations:
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 )
);
Les Onlines et BrickMorters auraient la même structure de base mais avec StoreType limité à "O" ou "B" selon le cas.
Maintenant, vous voulez une référence d'une autre table à TransactionalStores (et à travers elle aux différentes tables de magasin) mais limitée aux kiosques et à BrickMorter. La seule différence serait dans la contrainte:
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 )
);
Dans ce tableau, la référence FK force StoreType à être "K", "O" ou "B", mais la contrainte de champ la limite davantage à "K" ou "B" uniquement.
Pour illustration, j'ai utilisé une contrainte de vérification pour limiter les types de magasins dans la table TransactionStores. Dans la vraie vie, une table de recherche StoreTypes avec StoreType étant un FK pour cette table serait probablement un meilleur choix de conception.
Une clé étrangère ne peut pas être conditionnée, ce qui est hors de question. La règle commerciale semble être qu'un employé peut travailler pour un seul et unique magasin physique. Compte tenu de cela, le super type de magasin a deux sous-types comme vous l'avez suggéré: Physique et En ligne. Chaque magasin physique peut être occupé par un ou plusieurs employés, et chaque employé doit être affecté à un et un seul magasin physique. Les magasins physiques ont alors deux sous-types, Brick and Mortar et Kiosk. Avoir trois sous-types directs - Kiosk, Online, et Brick and Mortar - cache une propriété qui est possédée par chaque magasin - qu'il se trouve ou non à un emplacement physique. Désormais, la conception repose sur un humain pour comprendre la sémantique inhérente aux noms de sous-types pour comprendre que les magasins en ligne n'ont pas d'employés. Cela n'est pas évident dans le schéma déclaré et code sous la forme d'un déclencheur doit être écrit pour exprimer cette compréhension d'une manière que le SGBD peut appliquer. Développer, tester et maintenir un déclencheur qui n'affecte pas les performances est une solution beaucoup plus difficile à implémenter, comme le montre le livre Mathématiques appliquées aux professionnels de bases de données .
Sous-taper Store d'abord sur son type d'emplacement et ensuite sur le type de structure du magasin physique est une conception plus correcte par rapport aux règles métier et élimine la nécessité d'écrire du code pour appliquer la règle. Une fois que la propriété est clairement incluse en tant que type d'emplacement de magasin qui peut être utilisé comme discriminateur pour les sous-types, la relation peut être établie directement entre les employés et les magasins physiques et ainsi mettre pleinement en œuvre la règle uniquement avec la contrainte de clé étrangère. Voici un modèle de données créé avec Oracle SQL Developer Data Modeler qui montre le super et le sous-typage en utilisant Barker-Ellis case en notation de case pour les super et sous-types, qui Je préfère pour sa présentation élégante. Le diagramme peut désormais également montrer clairement la règle.