web-dev-qa-db-fra.com

Résolution de la relation Superype-sous-type sans sacrifier la cohérence des données dans une base de données relationnelle

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:

  1. Un magasin en ligne vend différentes catégories de product.
  2. Le système doit pouvoir récupérer la liste de toutes les catégories de produits, dire food et furniture.
  3. Un client peut commander n'importe quel produit et récupérer son historique order.
  4. Le système doit stocker des propriétés spécifiques en fonction de la catégorie de produits; dit le 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:

enter image description here

Le problème tente de résoudre les exigences 4. Je pensais à quelque chose comme ça:

enter image description here

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?

6
user174739

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.

2
Lennart

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.

1
nosurprisespls