Mysql
 sql >> Database >  >> RDS >> Mysql

MySQL - Progettazione di supertipi/sottotipi

Prima di iniziare, voglio sottolineare che "gas" descrive o carburante o un tipo di motore, non un tipo di berlina. Pensaci bene prima di continuare su questa strada. (La semantica è più importante nella progettazione di database di quanto la maggior parte delle persone pensi.)

Quello che vuoi fare è abbastanza semplice, ma non necessariamente facile. Il punto importante in questo tipo di design di supertipo/sottotipo (noto anche come arco esclusivo) è rendere impossibile avere file su berline che fanno riferimento a file su semirimorchi, ecc.

MySQL rende il codice più dettagliato, perché non applica i vincoli CHECK. Sei fortunato; nell'applicazione, i vincoli CHECK possono essere sostituiti da tabelle aggiuntive e vincoli di chiave esterna. I commenti si riferiscono all'SQL sopra loro.

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');

Questo è il tipo di cosa che potrei implementare come vincolo CHECK su altre piattaforme. Puoi farlo quando il significato dei codici è ovvio per gli utenti. Mi aspetto che gli utenti sappiano o capiscano che "s" è per semifinali e "c" è per auto, o che le visualizzazioni/il codice dell'applicazione nasconderebbero i codici agli utenti.

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)
);

Il vincolo UNIQUE consente alla coppia di colonne {veh_id, veh_type_code} di essere la destinazione di un riferimento di chiave esterna. Ciò significa che una riga "auto" non può fare riferimento a una riga "semi", nemmeno per errore.

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)
);

Qualcos'altro che implementerei come vincolo CHECK su altre piattaforme. (Vedi sotto.)

insert into veh_type_is_car values ('c');

Solo una riga per sempre.

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)
);

Il valore predefinito per veh_type_code, insieme al riferimento della chiave esterna a veh_type_is_car, garantisce che queste righe in questa tabella possano riguardare solo automobili e possono solo veicoli di riferimento che sono automobili. Su altre piattaforme, dichiarerei semplicemente la colonna veh_type_code come 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');

Se devi creare tabelle aggiuntive che facciano riferimento a berline, come gas_sedan, diesel_sedan, ecc., devi creare tabelle a una riga simili a "veh_type_is_car" e impostare loro riferimenti di chiave esterna.

In produzione, revocherei le autorizzazioni sulle tabelle di base e userei

  • viste aggiornabili per eseguire gli inserimenti e gli aggiornamenti, oppure
  • procedure memorizzate per eseguire gli inserimenti e gli aggiornamenti.