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

MySQL - Supertype/Subtype design

Inden jeg går i gang, vil jeg påpege, at "gas" beskriver enten brændstof eller en slags motor, ikke en slags sedan. Tænk dig godt om, før du fortsætter ad denne vej. (Semantik er vigtigere i databasedesign, end de fleste tror.)

Det, du vil gøre, er ret simpelt, men ikke nødvendigvis nemt. Den vigtige pointe i denne form for supertype/subtype-design (også kendt som en eksklusiv bue) er at gøre det umuligt at have rækker om sedans, der henviser til rækker om semi-lastbiler osv.

MySQL gør koden mere omfattende, fordi den ikke håndhæver CHECK-begrænsninger. Du er heldig; i din applikation kan CHECK-begrænsningerne erstattes af yderligere tabeller og fremmednøgle-begrænsninger. Kommentarer henviser til SQL ovenfor dem.

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

Det er den slags ting, jeg kan implementere som en CHECK-begrænsning på andre platforme. Det kan du gøre, når betydningen af ​​koderne er indlysende for brugerne. Jeg ville forvente, at brugerne ved eller finder ud af, at 's' er for semifinaler og 'c' er for biler, eller at visninger/applikationskode ville skjule koderne for brugerne.

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

Den UNIQUE begrænsning lader kolonneparret {veh_id, veh_type_code} være målet for en fremmednøglereference. Det betyder, at en "bil"-række umuligt kan henvise til en "semi"-række, selv ved en fejltagelse.

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

Noget andet, jeg ville implementere som en CHECK-begrænsning på andre platforme. (Se nedenfor.)

insert into veh_type_is_car values ('c');

Kun én række nogensinde.

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

Standardværdien for veh_type_code, sammen med den fremmede nøglereference til veh_type_is_car, garanterer, at denne række i denne tabel kun kan handle om biler og kun referencekøretøjer, der er biler. På andre platforme ville jeg bare erklære kolonnen veh_type_code som 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');

Hvis du skal bygge yderligere tabeller, der refererer til sedaner, såsom gas_sedans, diesel_sedans osv., så skal du bygge en-rækkede tabeller svarende til "veh_type_is_car" og angive fremmednøglereferencer til dem.

I produktionen ville jeg tilbagekalde tilladelser på basistabellerne og enten bruge

  • opdaterbare visninger til at udføre indsættelser og opdateringer, eller
  • lagrede procedurer til at udføre indsættelser og opdateringer.


  1. Generer klasse fra databasetabel

  2. DATEADD() Eksempler i SQL Server

  3. Rails 4 LIKE-forespørgsel - ActiveRecord tilføjer citater

  4. BDE vs ADO i Delphi