Essayer d'aller mieux à la conception de bases de données, j'ai remarqué que je suis toujours bloqué en essayant de résoudre les variations du même problème.
Voici un exemple en utilisant des exigences communes:
product
.food
et furniture
.order
.expiration_date
et calories
pour tout produit food
produit et manufacture_date
pour tout produit furniture
.Si ce n'était pas pour l'exigence 4, le modèle pourrait être assez simple:
Le problème tente de résoudre les exigences 4. Je pensais à quelque chose comme ça:
Dans cette approche, les relations product-furniture
et product-food
sont supertype-sous-type (ou superclass-sous-classe) d'associations; La clé principale du sous-type est également une clé étrangère de la clé primaire SuperType.
Cependant, cette approche ne peut pas garantir le category
_ référencé via une clé étrangère au product
sera cohérent avec son sous-type réel. Par exemple, rien ne m'empêche de définir food
Catégorie à un tuple de produit ayant une ligne de sous-type dans la table Furniture
.
J'ai lu divers articles sur l'héritage dans la modélisation des bases de données relationnelles, en particulier celui-ci et celui-ci qui étaient très utiles mais n'a pas résolu mon problème pour la raison mentionnée ci-dessus. Mais quel que soit le modèle que je vienne, je ne suis jamais satisfait de la cohérence des données.
Comment résoudre les exigences 4 sans sacrifier la cohérence des données? Est-ce que je vais tout faux ici? Si oui, quelle serait la meilleure façon de résoudre ce problème en fonction de ces exigences?
Un moyen courant est d'ajouter un classificateur "hérité" comme:
CREATE TABLE products
( product_id ... NOT NULL PRIMARY KEY
, ...
, product_type ... NOT NULL
, UNIQUE (product_id, products_type)
, CHECK (product_type IN ('food', 'furniture'))
);
produit_type serait généralement un code de type. Pourrait être une clé étrangère à une table "Recherche" au lieu d'une contrainte de contrôle. Pour les sous-types:
CREATE TABLE food
( product_id ... NOT NULL PRIMARY KEY
, ...
, product_type ... DEFAULT 'food' NOT NULL
, FOREIGN KEY (product_id, product_type)
REFERENCES products (product_id, product_type)
, CHECK (product_type = 'food')
);
et un semblable pour meubles. Les contraintes garantissent que produit_type est cohérent entre les sous-tables super- un.
Il y a des produits (j'ai entendu) qui permettent des sous-sélectionneurs dans les contraintes de contrôle, mais la majorité ne le font pas. Pour un tel produit quelque chose comme:
CREATE TABLE food
( product_id ... NOT NULL PRIMARY KEY
, ...
, FOREIGN KEY (product_id)
REFERENCES products (product_id)
, CHECK (
(SELECT product_type
FROM products p
WHERE p.product_id = product_id) = 'food'
)
);
peut être utilisé.
Une alternative à ce dernier est d'utiliser avant les déclencheurs pour insertion/mise à jour et signaler une exception si le mauvais produit_type est utilisé. Personnellement, je n'ai pas envie d'utiliser du code procédural pour des contraintes d'intégrité, mais je suppose que c'est une question de goût.
Peut-être que je simplifie l'exigence, mais de satisfaire l'exigence et votre préoccupation est de définir simplement les colonnes requises dans le sous-type pour ne pas null. Lorsqu'une nouvelle ligne de produits de produit est créée, une nouvelle ligne de nourriture sera également créée et si aucune information n'est fournie requise pour les aliments, la base de données rejetera la transaction.