MySQL - 超类型/子类型设计

2024-04-21

我需要创建以下数据库:

对于半卡车,我不需要额外的子类型,而对于汽车,我只需要这 3 个子类型,对于轿车,我需要四个子类型。 对于 SELECT,我将使用 JOIN(规范化数据库),但我需要找到一种简单的方法来进行 INSERT。

  • 车辆表存储常用信息
  • 半挂车存储半挂车的特定信息
  • 汽车表具有汽车的特定字段和链接到三个子类型的 car_type 字段
  • Van、Suv 和 Sedan(以及其他类型,如果我需要的话)应该位于一张表 CAR_TYPE 中
  • 但是,对于轿车类型,我需要有其他子类型,这些子类型可能应该包含在另一个表中。 Suv 和 Vans 不需要这些子类型(在现实生活中 suv 中,vans 可以具有与轿车相同的子类型,但在我的情况下则不然)。

我需要完全按照图中的方式创建该数据库。

到目前为止,我的第一个方法是拥有下表:

  • 车辆:veh_id、veh_type(半挂车、汽车)、...、other_fields
  • Vehicle_semis: veh_id, ..., other_semis_fields
  • Vehicle_car:veh_id、car_type(厢型车、SUV、轿车)、other_car_specific_fields
  • car_type:car_type_id,类型
  • Sedan_type:sedan_type_id,类型

我的问题是,我不确定这是否是正确的方法,并且我不确切知道如何在表之间创建关系。

有任何想法吗?

谢谢你!

UPDATE:

The following diagram is based on @Mike 's answer: enter image description here


在开始之前,我想指出“汽油”指的是燃料或一种发动机,而不是一种轿车。在你继续沿着这条路走之前,请仔细思考。 (语义在数据库设计中比大多数人想象的更重要。)

你想做的事情相当简单,但不一定容易。这种超类型/子类型设计(也称为独占弧)的重要一点是使有关轿车的行不可能引用有关半卡车等的行。

MySQL 使代码更加冗长,因为它不强制执行 CHECK 约束。你很幸运;在您的应用程序中,CHECK 约束可以替换为附加表和外键约束。注释参考SQLabove them.

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

我可能会在其他平台上将这种情况实现为 CHECK 约束。当代码的含义对用户来说很明显时,您可以这样做。我希望用户知道或弄清楚“s”代表半成品,“c”代表汽车,或者视图/应用程序代码会对用户隐藏代码。

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

UNIQUE 约束让一对列 {veh_id, veh_type_code} 成为外键引用的目标。这意味着“car”行不可能引用“semi”行,即使是错误的。

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

我会在其他平台上实现其他一些内容作为 CHECK 约束。 (见下文。)

insert into veh_type_is_car values ('c');

曾经只有一排。

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

veh_type_code 的默认值以及对 veh_type_is_car 的外键引用保证该表中的该行只能与汽车有关,并且可以only参考车辆是汽车。在其他平台上,我只需将 veh_type_code 列声明为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');

如果您必须构建引用轿车的其他表,例如gas_sedans、diesel_sedans等,那么您需要构建类似于“veh_type_is_car”的单行表并设置对它们的外键引用。

在生产中,我会撤销对基表的权限,然后使用

  • 可更新视图来执行插入和更新,或者
  • 执行插入和更新的存储过程。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL - 超类型/子类型设计 的相关文章

  • MySQL Workbench 6.0 错误无法获取管理员的管理访问权限?

    我在这里使用 MySQL Workbench 6 0 当我选择服务器状态时 出现此错误 对此 我尝试在Google和StackOverflow上寻找解决方案 e g 这个结果 https stackoverflow com question
  • SQL 检查一组日期是否在指定的日期范围内

    我有一个表 其中保存架构中房间不可用的日期 ROOM ID DATE UNAVAILABLE 我需要一个 sql 查询来检查两个日期范围内是否有可用房间 类似于 Select All rooms that are constantly av
  • MySQL用户创建的临时表已满

    我使用内存引擎创建了一个临时表 如下所示 CREATE TEMPORARY TABLE IF NOT EXISTS some text id INT DEFAULT 0 string varchar 400 DEFAULT engine m
  • mysql语句中的*星号是什么意思?

    Ex mysql query SELECT FROM members WHERE id id 这意味着选择表中的所有列
  • 通过货币换算获取每种产品类型的最低价格

    我想选择每种产品类型中最便宜的 包括运费 价格转换为当地货币 最便宜 产品 价格 产品 运费 seller to aud 我的数据库有如下表 PRODUCTS SELLERS id type id seller id price shipp
  • MySQL 存储过程将值分配给 select 语句中的多个变量

    这是我的存储过程 我在为声明的变量赋值时遇到问题 当我执行它时 插入和更新命令工作正常 但声明变量的值保持为 0 但我在数据库中有一些价值 我怎样才能正确地做到这一点 BEGIN DECLARE PaidFee INT DEFAULT 0
  • 在 MacOSX10.6 上运行 python 服务器时 MySQLdb 错误

    运行我的服务器 python manage py runserver 产生以下错误 django core exceptions ImproperlyConfigured 加载 MySQLdb 模块时出错 没有名为 MySQLdb 的模块
  • 将记录分成两列

    我的数据库中有一个 学生 表 其中包含大约 5 000 条记录 我想将这些记录显示在two分区 如何在不执行查询两次的情况下做到这一点 仅使用单个查询 显示示例http www freeimagehosting net uploads f1
  • 对于数据库来说,选择正确的数据类型会影响性能吗?

    如果是这样 为什么 我的意思是 tinyint 的搜索速度比 int 快吗 如果是这样 性能上的实际差异是什么 是的 根据数据类型 它确实有所不同 int vs tinyint不会在速度上产生明显的差异 但会在数据大小上产生差异 假设tin
  • 如何在 phpmyadmin 中创建 MySQL 触发器

    我想在 MySQL 中创建一个触发器 我运行以下命令 mysql gt delimiter mysql gt CREATE TRIGGER before insert money BEFORE INSERT ON money gt FOR
  • Hibernate 对集合的查询过滤器

    我想执行以下查询 from Item i where i categoryItems catalogId catId 然而 这会产生以下异常 非法尝试取消引用集合 所以我用谷歌搜索 找到了这个 Hibernate 论坛帖子https for
  • 当sql连接中存在两个同名列时,如何从一个表列中获取值

    当我连接两个具有相同名称列的表时 我目前面临着尝试获取值的问题 例如 table1 date和table2 date 每个表中的日期不同 我将如何获取 日期 本例中的表1 我目前正在跑步 while row mysqliquery gt f
  • 阻止注销页面后的后退按钮

    我有 php 注销页面 当用户单击注销链接时 请参阅此页面并重定向到索引页面 但是当单击后退按钮时 我会看到带有用户数据的上一页 当然 当我刷新页面时 我看不到以前的页面和数据 我在单击注销并单击后退按钮后检查了其他代码 drupal 但我
  • 如何在Mysql中仅将不同的值从一个表复制到另一个表?

    我有一个大约 2 5GB 的 MySql 数据库 表 A 具有以下列 anoid query date item rank url 我刚刚创建了另一个仅包含列的表 b query and date 我想在查询列中插入所有不同的记录 及其各自
  • MySQL 使用 ALTER IGNORE TABLE 出现重复错误

    我的 MySQL 中有一个有重复项的表 我尝试删除重复项并保留一项 我没有主键 我可以通过以下方式找到重复项 select user id server id count as NumDuplicates from user server
  • 如何在列上创建外键,该列的每条记录都可能引用多个表之一中的列?

    我正在创建一个社交网络 它有新闻 照片等多个实体 可以有评论 由于所有评论都具有相同的列并且行为方式相同 唯一的区别是它们的类型 新闻 照片或将来添加的其他内容 我决定为所有评论创建一个表 其中的列名为type 它工作得很好 直到我决定将外
  • MySQL MIN/MAX 所有行

    我有桌子Races与行ID Name and TotalCP 我选择分钟 TotalCP FROM Races 但是我想选择具有最小值的整行 我如何在单个查询中做到这一点 从聚合值获取整行的一般形式是 SELECT FROM Races W
  • MySQL Connector C/C API - 使用特殊字符进行查询

    我是一个 C 程序 我有一个接受域名参数的函数 void db domains query char name 使用 mysql query 我测试数据库中是否存在域名 如果不是这种情况 我插入新域名 char query 400 spri
  • MySQL 查询计算上个月

    我想计算上个月的订单总额 我收到了从当前日期获取当月数据的查询 SELECT SUM goods total AS Total Amount FROM orders WHERE order placed date gt date sub c
  • 将第三个表链接到多对多关联中的桥接表

    设计这个数据库的正确方法是什么 这是我设置表格的方式 我在名为 教师 的表和名为 仪器 的表之间存在多对多关系 然后我有一个连接两者的桥接表 我想将另一个表与 BRIDGE 表关联起来 意思是乐器 老师的组合 该表有 3 行 指定老师可以教

随机推荐