怎么为关系使用一个通用表

本教程将介绍如何为关系使用一个通用表的处理方法,这篇教程是从别的地方看到的,然后加了一些国外程序员的疑问与解答,希望能对你有所帮助,好了,下面开始学习吧。

怎么为关系使用一个通用表 教程 第1张

问题描述

我现在拥有的是硬编码"的表,以便在同一个表的两个与该表的两个外键之间建立关系.

在关系"表之前:

CREATE TABLE IF NOT EXISTS `Item_To_Item` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `item1_id` INT(11) NOT NULL,
  `item2_id` INT(11) NOT NULL,
  `relationship` ENUM('requires', 'mutually_requires', 'required_by', 'relates', 'excludes') NULL DEFAULT NULL,
  `description` VARCHAR(1000) NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `fk_Item1_Id`
 FOREIGN KEY (`item1_id`)
 REFERENCES `Item` (`id`)
  CONSTRAINT `fk_Item2_Id`
 FOREIGN KEY (`item2_id`)
 REFERENCES `Item` (`id`)

所以在此之前在项目表上有一个双多对一引用来填充两个外键.

现在需要在数据库中的表(枚举、标签、功能等)之间扩展这种关系以使其更通用.所以现在项目可以与项目相关,项目可以与标签相关,标签可以与带有枚举关系值的标签等相关.

我对通用表的想法是添加一个类型表,因此可以识别每个项目,标签等,然后将关系表重组为如下所示:

CREATE TABLE IF NOT EXISTS `Relationship` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `relater_id` INT(11) NOT NULL,
  `relatee_id` INT(11) NOT NULL,
  `relationship` ENUM('requires', 'mutually_requires', 'required_by', 'relates', 'excludes') NULL DEFAULT NULL,
  `description` VARCHAR(1000) NULL DEFAULT NULL,
  `relater_type_id` INT(11) NULL,
  `relatee_type_id` INT(11) NULL,
  PRIMARY KEY (`id`),
  INDEX `fk_Relatee_Id` (`relatee_id` ASC),
  INDEX `fk_Relater_Id` (`relater_id` ASC),
  CONSTRAINT `fk_Relater_Id`
 FOREIGN KEY (`relater_id`)
  CONSTRAINT `fk_Relatee_Id`
 FOREIGN KEY (`relatee_id`)

现在您可以通过 type_id 和 table 来识别哪些类型的项目,并且可以打开它,以便任何两个 table id 都可以进入 Relater 和 Relatee 外键列.

问题是我不知道怎么对外键进行这样的概括.我相信他们只能引用一张表,所以我不确定怎么使用通用键引用来做我想做的事.此外,我可以看到双向关系的问题,其中 A 相互需要 B 和 B 相互需要 A 是冗余数据.我可以在我的应用程序中阻止这种冗余,但我必须经常检查两侧的 A 到 B ||B 到 A.我想知道完成我想做的事情的最佳方式.谢谢.

也许为我的(项目、功能、标签)使用某种基本类型可以帮助我?

我认为答案并不像继承那么简单.至少据我所知.我的问题是,无论类型怎么,我都想关联两个一般项目.我不希望 20 列必须为空,因为它不是那种特定类型.我只是希望能够将两个 id 和两个 type_id 传递到关系中,这样我就可以关联任何两个对象.

推荐答案

一种可能的解决方案是实现 object_type 和 object_index 表:

CREATE TABLE object_type (
  `object_type_id` int(11) NOT NULL AUTO_INCREMENT,
  `object_type` varchar(30) NOT NULL,
  PRIMARY KEY (`object_type_id`),
  UNIQUE (`object_type`));

CREATE TABLE object_index (
  `object_id` int(11) NOT NULL AUTO_INCREMENT,
  `object_type_id` int(11) NOT NULL,
  PRIMARY KEY (`object_id`),
  UNIQUE (`object_type_id`, `object_id`));

并仅针对该表定义您的关系.

CREATE TABLE IF NOT EXISTS `Relationship` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `relater_id` INT(11) NOT NULL,
  `relatee_id` INT(11) NOT NULL,
  `relationship` ENUM('requires', 'mutually_requires', 'required_by', 'relates', 'excludes') NULL DEFAULT NULL,
  `description` VARCHAR(1000) NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  INDEX `fk_Relatee_Id` (`relatee_id` ASC),
  INDEX `fk_Relater_Id` (`relater_id` ASC),
  CONSTRAINT `fk_Relater_Id`
 FOREIGN KEY (`relater_id`)
 references object_index (`object_id`),
  CONSTRAINT `fk_Relatee_Id`
 FOREIGN KEY (`relatee_id`)
 references object_index (`object_id`));

接下来定义每个对象表,使其与唯一 (object_type_id, object_id) 元组上的 object_index 相关联.在这个例子中,每个表默认和检查约束 object_type_id 应该是唯一的:

CREATE TABLE table1 (
  `object_id` int(11) NOT NULL,
  `object_type_id` int(11) NOT NULL DEFAULT 1 CHECK (object_type = 1),
  `col1` varchar(4),
  PRIMARY KEY (`object_id`),
  CONSTRAINT fk_t1_ob_idx
 FOREIGN KEY (`object_type_id`, `object_id`)
 REFERENCES object_index (`object_type_id`, `object_id`));

在 MySQL 5.6 及更高版本中,您可以在每个表上定义一个虚拟/计算列,以匹配来自 object_index 的 object_type_id 而不是存储的物理列.

在 MySQL 8.0 及更高版本中,您可能能够在每个表上定义一个基于函数的索引,该索引将鉴别器 object_type_id 作为表达式而不是表中的物理或虚拟列.

好了关于怎么为关系使用一个通用表的教程就到这里就结束了,希望趣模板源码网找到的这篇技术文章能帮助到大家,更多技术教程可以在站内搜索。