许可证规范化 类

Normalization of Licence Classes

如何存储有关 class 个许可证的数据?

数据子集是拥有执照的人和拥有执照的人 类。

感谢@karmakaze 绘制此图。

+------+    +-------+     +---------+
|person|---*|licence|---1*|lic_class|
+------+    +-------+     +---------+

people table 有 person_id 和各种名称字段。

许可证具有由政府机构颁发的具有有效期的唯一编号,许可证有多个 classes。

最初我打算将 licenses table 构造为 lut_training(上面的 a.k.a lic_class)和之间的链接 table people

CREATE TABLE `licences` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `person_id` int(10) unsigned NOT NULL,
  `training_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `person_id` (`person_id`),
  KEY `training_id` (`training_id`),
  CONSTRAINT `licences_ibfk_3` FOREIGN KEY (`person_id`) REFERENCES `people` (`person_id`) ON UPDATE CASCADE,
  CONSTRAINT `licences_ibfk_4` FOREIGN KEY (`training_id`) REFERENCES `lut_training` (`training_id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

lut_training table 最初只是一个查找 table 来处理许可证 classes 的短名称和长名称,例如(id="6", short="1F", long="1F 武装警卫队")。

然后我需要将 licence_numberexpiry_date 放在某个地方,这样它就可以进入 licences(可能是它的最佳位置)或 lut_training。我选择了 lut_training,但这可能是糟糕的数据库设计。

CREATE TABLE `lut_training` (
  `training_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `training_short` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL,
  `training_long` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
  `expiry_date` date DEFAULT NULL,
  `licence_number` int(10) unsigned NOT NULL,
  PRIMARY KEY (`training_id`),
  KEY `training_long` (`training_long`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

然后我发现每个许可证 class 都没有自己的编号或有效期,这与我拥有的其他 8 个政府许可证不同。加上classes可以随意增减。所以将 expiry_date 和 licence_number 字段放在 lic_class table.

中是没有意义的

10 class 目前存在 1A,1B,1C,1D,1E,1F,2A,2B,2C,2D。有人可能从 1A 和 1E 开始,添加 1C,然后删除 1A 并保留 1E 和 1C,直到他们的许可证到期。

所以现在创建 lut_training 并为每个许可证放一行 class 似乎很愚蠢且效率低下,因为数据集中的大多数人都是多人 class 被许可人。

所以我可以这样做并使用 licence 中的 1 个字段来持有许可证的 classes:

+------+    +-------+
|person|---*|licence|
+------+    +-------+

这有点像 WordPress.org wp_options table 是一堆 key:value 对。

作为SQL

CREATE TABLE `licences` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `person_id` int(10) unsigned NOT NULL,
  `expiry_date` date DEFAULT NULL,
  `licence_number` int(10) unsigned NOT NULL,
  `licence_types` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`id`),
  KEY `person_id` (`person_id`),
  CONSTRAINT `licences_ibfk_3` FOREIGN KEY (`person_id`) REFERENCES `people` (`person_id`) ON UPDATE CASCADE,
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

我遇到的问题是 licence_types varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL, 甚至 licence_types smallint NOT NULL,

这似乎违反了数据库规范化,特别是 1NF 第一范式。

此外,如果我使用字符串或整数字段而不是单独的 lic_class table,我将不得不进行字符串或整数操作以更新许可证 classes。 10 license classes 表示 2^10=1024 位数据或一些伪数组或文字数组字段,用于存储一个人持有的所有 license class 组合。这不是很多 space.

感谢有关如何解决此问题的指导。

希望批评者更清楚这一点。

据我所知,一个人可以拥有零个或多个许可证(来自不同政府),每个许可证可以有一个或多个许可 classes。

+------+    +-------+     +---------+
|person|---*|licence|---1*|lic_class|
+------+    +-------+     +---------+

到期日期将与许可证一起使用。您可以选择将许可 classes 反规范化为许可,具体取决于每个许可 class.

数据的 much/little 方式。

棘手的一点是约束。 license (person_id, government) 上应该有唯一约束。 lic_class(licence_id, license_type) 也应该有一个唯一的约束,因为你不能多次拥有相同的类型。