Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL - Supertype/Subtype-Design

Bevor ich anfange, möchte ich darauf hinweisen, dass "Benzin" entweder Kraftstoff oder eine Art Motor beschreibt, nicht eine Art Limousine. Denken Sie gut nach, bevor Sie diesen Weg weitergehen. (Semantik ist beim Datenbankdesign wichtiger als die meisten Leute denken.)

Was Sie tun möchten, ist ziemlich einfach, aber nicht unbedingt einfach. Der wichtige Punkt bei dieser Art von Supertype/Subtype-Design (auch als exklusiver Bogen bekannt) besteht darin, es unmöglich zu machen, Zeilen über Limousinen zu haben, die auf Zeilen über Sattelzugmaschinen usw. verweisen.

MySQL macht den Code ausführlicher, weil es keine CHECK-Einschränkungen erzwingt. Du hast Glück; In Ihrer Anwendung können die CHECK-Einschränkungen durch zusätzliche Tabellen und Fremdschlüsseleinschränkungen ersetzt werden. Kommentare beziehen sich auf die SQL oben sie.

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

So etwas könnte ich als CHECK-Einschränkung auf anderen Plattformen implementieren. Sie können dies tun, wenn die Bedeutung der Codes für die Benutzer offensichtlich ist. Ich würde erwarten, dass Benutzer wissen oder herausfinden, dass 's' für Semis und 'c' für Autos steht, oder dass Views/Anwendungscode die Codes vor Benutzern verbergen würde.

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

Die UNIQUE-Einschränkung lässt das Spaltenpaar {veh_id, veh_type_code} das Ziel einer Fremdschlüsselreferenz sein. Das bedeutet, dass eine „Auto“-Zeile unmöglich auf eine „Halb“-Zeile verweisen kann, nicht einmal aus Versehen.

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

Etwas anderes würde ich als CHECK-Einschränkung auf anderen Plattformen implementieren. (Siehe unten.)

insert into veh_type_is_car values ('c');

Immer nur eine Zeile.

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

Der Standardwert für veh_type_code, zusammen mit dem Fremdschlüsselverweis auf veh_type_is_car, garantiert, dass diese Zeilen in dieser Tabelle sich nur auf Autos beziehen können und nur Referenzfahrzeuge, die Autos sind. Auf anderen Plattformen würde ich die Spalte veh_type_code einfach als veh_type_code char(1) not null default 'c' check (veh_type_code = 'c') deklarieren .

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

Wenn Sie zusätzliche Tabellen erstellen müssen, die auf Limousinen verweisen, wie z. B. gas_sedans, diesel_sedans usw., müssen Sie einzeilige Tabellen ähnlich wie "veh_type_is_car" erstellen und Fremdschlüsselreferenzen darauf setzen.

In der Produktion würde ich Berechtigungen für die Basistabellen widerrufen und entweder

verwenden
  • aktualisierbare Ansichten zum Einfügen und Aktualisieren oder
  • gespeicherte Prozeduren für die Einfügungen und Aktualisierungen.