【问题标题】:mysql - referencing one foreign key to multiple possible primary keysmysql - 将一个外键引用到多个可能的主键
【发布时间】:2012-07-15 04:59:32
【问题描述】:

我想设置以下数据库场景:

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_byme_last_modified_by 的字段应引用存储一些用户数据的表。

【问题讨论】:

  • 您的表 Points 和 Lines 是否可以改为引用元数据,即在这两个表中都放置一个外键 'metadata_id'?

标签: mysql database-design foreign-keys


【解决方案1】:

您的案例似乎是称为“泛化专业化”或“类继承的表设计”的设计模式的另一个实例。

如果您将点和线视为对象的类别,那么它们都是一些更一般的对象类别的子类。我不确定在这种情况下给超类起什么名字。这是解决同一问题的几个先前问题之一。

Extending classes in the database

福勒对这个主题进行了广泛的处理。您的案例有一个额外的问题,因为您正在处理元数据。但这不需要改变设计。您需要第三张表,由于没有更好的术语,我将其称为“项目”。键“it_id”将被分配一个自动编号,每次添加点或线时,您都会添加一个项目。不会为“po_id”和“li_id”两列分配自动编号。相反,它们将是外键,在 Items 表中引用“it_id”。

元数据表中对点或线的引用将成为对“项目”的引用,您可以根据具体情况使用该信息查找有关点或线的信息。

这有多大帮助取决于您尝试对元数据执行的操作。

【讨论】:

  • 这个解决方案对我来说很有趣,我会按照你的建议阅读一些给定的文章。谢谢
【解决方案2】:

您的表pointslines 应该包含metadata 的外键——而不是相反。这样做将使您免于定义任何更复杂的表格设置。使用这种方法,单个metadata-entry 可以多次重复用于许多不同的点或线。这甚至不是 MySQL 特有的,而是一种通用的、标准化的数据库结构。

【讨论】:

  • 啊,我没有这么想。这似乎是解决我的问题的最简单的解决方案。谢谢
  • @mgr 这是关系数据库中的“默认”方式。您应该阅读有关database normalization 的内容。
【解决方案3】:

您可以使用触发器来执行此操作,您需要先触发一个可以为点或线创建引用键的事件,然后再根据相应的表插入记录

【讨论】:

  • 我认为经理正在询问如何构造数据库模式,以便表可以具有一个表或另一个不同表中的主字段的外键。还是您的意思是使用触发器而不是约束来检查引用完整性?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-31
  • 1970-01-01
  • 2012-07-02
相关资源
最近更新 更多