我如何存储有关许可类别的数据?
数据子集是具有许可证的人和具有类别的许可证。
感谢@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_number
和expiry_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位数据或某个伪数组或文字数组字段,用于存储一个人拥有的所有许可证类别组合。这不是很多空间。
赞赏如何实现这一目标的方向。
希望批评者更清楚。
正如我所看到的,一个人可以拥有零个或多个许可(来自不同政府),每个许可可以具有一个或多个许可类。
+------+ +-------+ +---------+
|person|---*|licence|---1*|lic_class|
+------+ +-------+ +---------+
到期日期与许可证一起。您可以选择根据许可类中有多少数据来将许可类归一化为许可。
棘手的是约束。 license (person_id, government)
应该有唯一的约束。 lic_class(licence_id, license_type)
上还应该有一个唯一的约束,因为您不能一次拥有同一类型。