许可证类别的规范化

问题描述 投票:-1回答:1

我如何存储有关许可类别的数据?

数据子集是具有许可证的人和具有类别的许可证。

感谢@karmakaze提供此图。

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

people表具有person_id和各种名称字段。

许可证具有政府机构颁发的唯一编号,且具有到期日期,许可证具有多个类别。

最初,我打算将licenses表构造为lut_training(也就是上面的lic_class)和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表最初只是一个查找表,用于处理许可证类别的短名称和长名称,例如(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;

然后我发现,与我拥有的其他8个政府许可证不同,每个许可证类别都没有自己的编号或有效期。 Plus类可以随意添加和删除。因此,将expiry_date和licence_number字段放入lic_class表毫无意义。

10个类别当前存在1A,1B,1C,1D,1E,1F,2A,2B,2C,2D。有人可能以1A和1E开始,添加1C,然后放下1A,并保留1E和1C,直到他们的许可证过期。

因此,现在复制很多数据,因为数据集中的大多数人都是多类被许可人,因此创建lut_training并为每个许可类添加一行似乎很愚蠢且效率低下。

所以我可以这样做,并在licence中使用1个字段来保存许可证的类别:

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

有点像WordPress.org wp_options表是一堆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表,则必须执行字符串或整数操作才能更新许可证类。 10个许可证类别表示2 ^ 10 = 1024位数据或某个伪数组或文字数组字段,用于存储一个人拥有的所有许可证类别组合。这不是很多空间。

赞赏如何实现这一目标的方向。

希望批评者更清楚。

mysql database-normalization
1个回答
1
投票

正如我所看到的,一个人可以拥有零个或多个许可(来自不同政府),每个许可可以具有一个或多个许可类。

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

到期日期与许可证一起。您可以选择根据许可类中有多少数据来将许可类归一化为许可。

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

© www.soinside.com 2019 - 2024. All rights reserved.