怎么为关系使用一个通用表
本教程将介绍如何为关系使用一个通用表的处理方法,这篇教程是从别的地方看到的,然后加了一些国外程序员的疑问与解答,希望能对你有所帮助,好了,下面开始学习吧。
问题描述
我现在拥有的是硬编码"的表,以便在同一个表的两个与该表的两个外键之间建立关系.
在关系"表之前:
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 作为表达式而不是表中的物理或虚拟列.
好了关于怎么为关系使用一个通用表的教程就到这里就结束了,希望趣模板源码网找到的这篇技术文章能帮助到大家,更多技术教程可以在站内搜索。