我想设置以下数据库场景:
CREATE TABLE IF NOT EXISTS `points` (
`po_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`po_north` INT,
`po_east` INT,
PRIMARY KEY (`po_id`),
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `lines`(
`li_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`li_from` INT NOT NULL,
`li_to` INT NOT NULL,
PRIMARY KEY (`li_id`),
FOREIGN KEY (`li_from`) REFERENCES points(`po_id`),
FOREIGN KEY (`li_to`) REFERENCES points(`po_id`),
) ENGINE=InnoDB;
现在我想设置一个第三个表,用于处理一些元数据,例如谁创建或更改了一个点或一行:
CREATE TABLE IF NOT EXISTS `metadata` (
`me_type` ENUM('point','line') NOT NULL,
`me_type_id` INT UNSIGNED NOT NULL,
`me_permissions` VARCHAR(255) NOT NULL,
`me_created_by` INT UNSIGNED NOT NULL,
`me_created_on` DATETIME NOT NULL,
`me_last_modified_by` INT UNSIGNED NOT NULL,
`me_last_modified_by` DATETIME NOT NULL,
) ENGINE=InnoDB;
我的第一种方法是设置ENUM
有两种类型(点和线)。但问题仍然是,我无法正确引用其中一个表的外键。在MySQL中是否有针对此类问题的推荐解决方案?
顺便说一句:
me_created_by
和me_last_modified_by
的字段应引用存储某些用户数据的表。
答案 0 :(得分:1)
您的案例似乎是设计模式的另一个实例,称为“泛化专业化”或“类继承的表设计”。
如果将点和线视为对象类,它们都是一些更通用的对象类的子类。在这种情况下,我不确定给出超类的名称。以下是解决同一问题的几个问题之一。
Extending classes in the database
Fowler对该主题进行了广泛的治疗。您的案例有一个额外的皱纹,因为您正在处理元数据。但这不需要改变设计。你需要第三张桌子,因为缺少一个更好的术语,我称之为“项目”。键“it_id”将被分配一个自动编号,每次添加一个点或一行时都会添加一个项目。两列“po_id”和“li_id”不会被分配一个自动编号。相反,它们将是外键,在Items表中引用“it_id”。
元数据表中对点或线的引用将引用“项目”,您可以根据具体情况使用该信息查找有关点或线的信息。
这有多大帮助取决于您尝试使用元数据做什么。
答案 1 :(得分:0)
您的表格points
和lines
应该包含metadata
的外键 - 而不是相反。这样做可以避免定义任何更复杂的表设置。使用这种方法,对于许多不同的点或线,可以多次重复使用单个metadata
条目。这甚至不是MySQL特有的,而是一般的标准化数据库结构。
答案 2 :(得分:-1)
你可以使用触发器执行此操作,在根据相应的表插入记录之前,需要触发可以为点或行创建引用键的事件