Quelle est la meilleure façon d'émuler Tagged Union dans des bases de données?
Je parle de quelque chose comme ceci: où le véhicule_id serait ID dans la table de voitures ou la table de l'automobile, et sachez que. P> (supposons que le moteur et Les tables de voiture n'ont rien de commun0 p> p>
4 Réponses :
CREATE TABLE vehicle (type INT NOT NULL, id INT NOT NULL, PRIMARY KEY (type, id) ) CREATE TABLE car (type INT NOT NULL DEFAULT 1, id INT NOT NULL PRIMARY KEY, CHECK(type = 1), FOREIGN KEY (type, id) REFERENCES vehicle ) CREATE TABLE motorcycle (type INT NOT NULL DEFAULT 2, id INT NOT NULL PRIMARY KEY, CHECK(type = 2), FOREIGN KEY (type, id) REFERENCES vehicle ) CREATE TABLE t1 ( ... vehicle_type INT NOT NULL, vehicle_id INT NOT NULL, FOREIGN KEY (vehicle_type, vehicle_id) REFERENCES vehicle ... )
Cela faciliterait la vie si vous avez défini véhicule.vehicle_id code> comme clé principale afin de ne pas avoir à faire référence à une clé composite et que vous avez des colonnes de type et d'identité à l'aide d'une contrainte unique.
@OMG Ponies: Code> Avec cette mise en page, vous n'avez pas besoin de référencer
véhicule code> du tout. Vous pouvez simplement rejoindre
voitures code> ou
motocycles code>, en fonction du type
code>.
Véhicule Code> Ici ne sert que de policier les relations.
Avec cette méthode, existe-t-il un moyen de garantir qu'il n'y aura pas de "orpheline" des véhicules qui n'ont pas une ligne correspondante dans voiture code> ou
motocyclycle code>?
Certaines personnes utilisent une conception appelée associations polymorphes pour le faire, permettant Le problème est que vous ne pouvez pas déclarer une vraie contrainte de clé étrangère SQL si vous faites cela. Il n'y a pas de support dans SQL pour une clé étrangère comportant plusieurs cibles de référence. Il y a aussi d'autres problèmes, mais le manque d'intégrité référentielle est déjà un pot-casseur. P> Un meilleur design consiste à emprunter un concept de la conception de OO d'un Superype em> de véhicule_id code> contenir une valeur qui existe dans
voiture code> ou
Moteur code> . Ajoutez ensuite un
véhicule_type code> qui nomme la table que la ligne donnée dans
t1 code> références.
voiture code> et
Moteur CODE>: P>
CREATE TABLE car (
id INTEGER NOT NULL,
FOREIGN KEY (id) REFERENCES identifiable(id)
...
);
CREATE TABLE motor (
id INTEGER NOT NULL,
FOREIGN KEY (id) REFERENCES identifiable(id)
...
);
La clé de substitution pour identifiable code> est seulement bonne quand il y a des attributs dans
identifiables code> que la requête doit sélectionner. Si
identifiable code> ne sert à appliquer les contraintes, à l'aide d'une clé composite permettra de s'en débarrasser dans les requêtes sur les questions.
J'ai monté et j'ai utilisé l'approche "Common Superype", et l'a utilisé avec succès dans les principaux projets de migration / réaménagement du système. (Gouvernement NZ, Spot25 pour la MEO)
Je pense que vous pouvez modéliser une telle référence en utilisant héritage de table dans PostgreSQL .
Si vous avez vraiment besoin de savoir où une ligne vient dans une requête, vous pouvez utiliser une simple syndicat toutes les déclarations telles que (cette possibilité n'a rien à voir avec la table héritage): P> < Pré> xxx pré> p>
Je pense que la solution la moins achalandée est d'utiliser Par exemple, considérez cette adt dans HASKELLL: P> contrainte code> et
vérifier code>.
CREATE TABLE shape (
type ENUM('circle', 'rectangle') NOT NULL,
radius FLOAT,
width FLOAT,
height FLOAT,
CONSTRAINT constraint_circle CHECK
(type <> 'circle' OR radius IS NOT NULL),
CONSTRAINT constraint_rectangle CHECK
(type <> 'rectangle' OR (width IS NOT NULL AND height IS NOT NULL))
);
INSERT INTO shape(type, radius, width, height)
VALUES ('circle', 1, NULL, NULL); -- ok
INSERT INTO shape(type, radius, width, height)
VALUES ('circle', NULL, 1, NULL); -- error, constraint_circle violated
FWIW: Dire type <> x ou y code> est en réalité équivalente à l'implication:
type = x => y code>. Une autre expression équivalente (sans doute à digérer) serait
non (type = x et non y) code>. C'est à dire. Il est pas b> autorisé à être b> un cercle et non b> pour avoir un rayon. Votre version est transformée en une forme plus compacte à l'aide de la législation de De Morgan.