Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

MySQL - design de supertipo/subtipo


Antes de começar, quero salientar que "gás" descreve combustível ou um tipo de motor, não um tipo de sedã. Pense bem antes de continuar seguindo esse caminho. (A semântica é mais importante no design de banco de dados do que a maioria das pessoas pensa.)

O que você quer fazer é bastante simples, mas não necessariamente fácil. O ponto importante neste tipo de design de supertipo/subtipo (também conhecido como arco exclusivo) é tornar impossível ter filas sobre sedãs referenciando filas sobre semi-caminhões, etc.

O MySQL torna o código mais detalhado, porque não impõe restrições CHECK. Você é sortudo; em seu aplicativo, as restrições CHECK podem ser substituídas por tabelas adicionais e restrições de chave estrangeira. Os comentários referem-se ao SQL acima eles.
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');

Esse é o tipo de coisa que eu poderia implementar como uma restrição CHECK em outras plataformas. Você pode fazer isso quando o significado dos códigos for óbvio para os usuários. Eu esperaria que os usuários soubessem ou descobrissem que 's' é para semis e 'c' é para carros, ou que o código de visualização/aplicativo ocultaria os códigos dos usuários.
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)
);

A restrição UNIQUE permite que o par de colunas {veh_id, veh_type_code} seja o destino de uma referência de chave estrangeira. Isso significa que uma linha "carro" não pode referenciar uma linha "semi", mesmo por engano.
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)
);

Outra coisa que eu implementaria como uma restrição CHECK em outras plataformas. (Ver abaixo.)
insert into veh_type_is_car values ('c');

Apenas uma linha de 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)
);

O valor padrão para veh_type_code, juntamente com a referência de chave estrangeira para veh_type_is_car, garante que essas linhas nesta tabela possam ser apenas sobre carros e somente veículos de referência que são carros. Em outras plataformas, eu apenas declararia a coluna veh_type_code como 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 você tiver que construir tabelas adicionais que referenciam sedans, como gas_sedans, diesel_sedans, etc., então você precisa construir tabelas de uma linha semelhantes a "veh_type_is_car" e definir referências de chave estrangeira para elas.

Na produção, eu revogaria as permissões nas tabelas base e usaria
  • visualizações atualizáveis ​​para fazer as inserções e atualizações, ou
  • procedimentos armazenados para fazer as inserções e atualizações.