Mysql
 sql >> Base de données >  >> RDS >> Mysql

MySQL - Conception de supertype/sous-type

Avant de commencer, je tiens à souligner que "essence" décrit soit un carburant, soit une sorte de moteur, pas une sorte de berline. Réfléchissez bien avant de continuer dans cette voie. (La sémantique est plus importante dans la conception de bases de données que la plupart des gens ne le pensent.)

Ce que vous voulez faire est assez simple, mais pas nécessairement facile. Le point important dans ce type de conception de supertype/sous-type (également connu sous le nom d'arc exclusif) est de rendre impossible d'avoir des lignes sur les berlines référençant des lignes sur les semi-remorques, etc.

MySQL rend le code plus détaillé, car il n'applique pas les contraintes CHECK. Tu es chanceux; dans votre application, les contraintes CHECK peuvent être remplacées par des tables supplémentaires et des contraintes de clé étrangère. Les commentaires se réfèrent au SQL ci-dessus eux.

create table vehicle_types (
  veh_type_code char(1) not null,
  veh_type_name varchar(10) not null,
  primary key (veh_type_code),
  unique (veh_type_name)
);

insert into vehicle_types values
('s', 'Semi-truck'), ('c', 'Car');

C'est le genre de chose que je pourrais implémenter comme contrainte CHECK sur d'autres plates-formes. Vous pouvez le faire lorsque la signification des codes est évidente pour les utilisateurs. Je m'attendrais à ce que les utilisateurs sachent ou comprennent que 's' est pour les demi-finales et 'c' est pour les voitures, ou que les vues/le code d'application cacheraient les codes aux utilisateurs.

create table vehicles (
  veh_id integer not null,
  veh_type_code char(1) not null,
  other_columns char(1) default 'x',
  primary key (veh_id),
  unique (veh_id, veh_type_code),
  foreign key (veh_type_code) references vehicle_types (veh_type_code)
);

La contrainte UNIQUE permet à la paire de colonnes {veh_id, veh_type_code} d'être la cible d'une référence de clé étrangère. Cela signifie qu'une ligne "car" ne peut pas faire référence à une ligne "semi", même par erreur.

insert into vehicles (veh_id, veh_type_code) values
(1, 's'), (2, 'c'), (3, 'c'), (4, 'c'), (5, 'c'), 
(6, 'c'), (7, 'c');

create table car_types (
  car_type char(3) not null,
  primary key (car_type)
);

insert into car_types values
('Van'), ('SUV'), ('Sed');

create table veh_type_is_car (
  veh_type_car char(1) not null,
  primary key (veh_type_car)
);

Quelque chose d'autre que j'implémenterais comme contrainte CHECK sur d'autres plates-formes. (Voir ci-dessous.)

insert into veh_type_is_car values ('c');

Une seule ligne jamais.

create table cars (
  veh_id integer not null,
  veh_type_code char(1) not null default 'c',
  car_type char(3) not null,
  other_columns char(1) not null default 'x',
  primary key (veh_id ),
  unique (veh_id, veh_type_code, car_type),
  foreign key (veh_id, veh_type_code) references vehicles (veh_id, veh_type_code),
  foreign key (car_type) references car_types (car_type),
  foreign key (veh_type_code) references veh_type_is_car (veh_type_car)
);

La valeur par défaut de veh_type_code, ainsi que la référence de clé étrangère à veh_type_is_car, garantit que les lignes de cette table ne peuvent concerner que les voitures et uniquement véhicules de référence qui sont des voitures. Sur d'autres plateformes, je déclarerais simplement la colonne veh_type_code comme veh_type_code char(1) not null default 'c' check (veh_type_code = 'c') .

insert into cars (veh_id, veh_type_code, car_type) values
(2, 'c', 'Van'), (3, 'c', 'SUV'), (4, 'c', 'Sed'),
(5, 'c', 'Sed'), (6, 'c', 'Sed'), (7, 'c', 'Sed');

create table sedan_types (
  sedan_type_code char(1) not null,
  primary key (sedan_type_code)
);

insert into sedan_types values
('g'), ('d'), ('h'), ('e');

create table sedans (
  veh_id integer not null,
  veh_type_code char(1) not null,
  car_type char(3) not null,
  sedan_type char(1) not null,
  other_columns char(1) not null default 'x',
  primary key (veh_id),
  foreign key (sedan_type) references sedan_types (sedan_type_code),
  foreign key (veh_id, veh_type_code, car_type) references cars (veh_id, veh_type_code, car_type)
);

insert into sedans (veh_id, veh_type_code, car_type, sedan_type) values 
(4, 'c', 'Sed', 'g'), (5, 'c', 'Sed', 'd'), (6, 'c', 'Sed', 'h'),
(7, 'c', 'Sed', 'e');

Si vous devez créer des tables supplémentaires faisant référence à des berlines, telles que gas_sedans, diesel_sedans, etc., vous devez créer des tables à une ligne similaires à "veh_type_is_car" et leur définir des références de clé étrangère.

En production, je révoquerais les autorisations sur les tables de base et utiliserais

  • des vues actualisables pour faire les insertions et les mises à jour, ou
  • procédures stockées pour effectuer les insertions et les mises à jour.