sql >> Base de Datos >  >> RDS >> Mysql

MySQL - Diseño de supertipos/subtipos

Antes de comenzar, quiero señalar que "gasolina" describe combustible o un tipo de motor, no un tipo de sedán. Piensa bien antes de seguir por este camino. (La semántica es más importante en el diseño de bases de datos de lo que la mayoría de la gente piensa).

Lo que quieres hacer es bastante simple, pero no necesariamente fácil. El punto importante en este tipo de diseño de supertipo/subtipo (también conocido como arco exclusivo) es hacer que sea imposible tener filas sobre sedanes que hagan referencia a filas sobre semirremolques, etc.

MySQL hace que el código sea más detallado, porque no aplica las restricciones CHECK. Tienes suerte; en su aplicación, las restricciones CHECK se pueden reemplazar por tablas adicionales y restricciones de clave externa. Los comentarios se refieren al SQL anterior ellos.

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

Este es el tipo de cosas que podría implementar como una restricción CHECK en otras plataformas. Puede hacerlo cuando el significado de los códigos sea obvio para los usuarios. Espero que los usuarios sepan o se den cuenta de que 's' es para semirremolques y 'c' para automóviles, o que el código de vista/aplicación ocultaría los códigos a los usuarios.

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 restricción ÚNICA permite que el par de columnas {veh_id, veh_type_code} sea el objetivo de una referencia de clave externa. Eso significa que una fila "coche" no puede hacer referencia a una fila "semi", ni siquiera por error.

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

Algo más que implementaría como una restricción CHECK en otras plataformas. (Ver más abajo).

insert into veh_type_is_car values ('c');

Solo una fila.

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

El valor predeterminado para veh_type_code, junto con la referencia de clave externa a veh_type_is_car, garantiza que estas filas en esta tabla solo pueden ser sobre autos, y pueden solo vehículos de referencia que son automóviles. En otras plataformas, simplemente declararía la columna 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');

Si tiene que crear tablas adicionales que hagan referencia a sedanes, como gas_sedans, diesel_sedans, etc., entonces necesita crear tablas de una fila similares a "veh_type_is_car" y establecer referencias de clave externa para ellas.

En producción, revocaría los permisos en las tablas base y usaría

  • vistas actualizables para hacer las inserciones y actualizaciones, o
  • procedimientos almacenados para hacer inserciones y actualizaciones.