MYSQL - 一列引用多表

标签 mysql sql database-design data-modeling referential-integrity

一个表中的单个列可以被多个表引用吗?

最佳答案

一个很晚的答案,但对于那些想知道和谷歌搜索的人来说。

YES 这是可以做到的,但这不是好的做法,即使它很简单,它也可能在你的脸上爆炸 em> 如果你不是很清楚自己在做什么。不推荐。

但是,我可以看到用途。例如,您有一个包含数百万条记录的大表,并且您希望在特殊情况下链接到未知或多个表(在这种情况下最好是 许多)。对于多个表,如果您要为所有表创建一个外键,那将大大增加您的数据库大小。例如,在技术支持系统中可能会出现未知表,您希望链接到可能存在问题的表中的记录,这可能(几乎)是数据库中的所有表,包括 future 的表。

当然,您需要两个 字段来链接:一个外键字段和它链接到的表的名称。让我们称它们为 foreignIdlinkedTable

linkedTable 可以是枚举或字符串,最好是枚举(较少空间),但这只有在您要链接到的不同表是固定的情况下才有可能。

让我们举一个极其愚蠢的例子。您有一个巨大的用户表 users,其中一些用户可以恰好将 一个 个人数据集添加到他们的个人资料中。这可以是关于他们的爱好、宠物、他们从事的一项运动他们的职业。现在,此信息在所有四种情况下都不同。 (实际上 4 个可能的表不足以足以证明这种结构)

现在假设 linkedTable 是一个枚举,可能的值为 petshobbiessports professions,这是四个不同结构的表的名称。假设 id 是所有四个中的 pkey。

你加入例如如下:

SELECT * FROM users 
    LEFT JOIN  pets        ON linkedTable = 'pets'        AND foreignId = pets.id
    LEFT JOIN  hobbies     ON linkedTable = 'hobbies'     AND foreignId = hobbies.id
    LEFT JOIN  sports      ON linkedTable = 'sports'      AND foreignId = sports.id
    LEFT JOIN  professions ON linkedTable = 'professions' AND foreignId = professions.id

这只是一个基本的笑话。由于您可能只在极少数情况下需要链接,因此当您循环访问用户(不加入)时,您更有可能使用您的编程语言(如 PHP)进行查找。

想试试吗?您可以自己尝试构建此测试数据库(确保您使用的是测试数据库):

CREATE TABLE IF NOT EXISTS `users` (
    `id` INT NOT NULL AUTO_INCREMENT , 
    `name` VARCHAR(100) NOT NULL , 
    `linkedTable` ENUM('pets','hobbies','sports','professions') NULL DEFAULT NULL , 
    `foreignId` INT NULL DEFAULT NULL , 
  PRIMARY KEY (`id`), INDEX (`linkedTable`)
) ;

CREATE TABLE  IF NOT EXISTS `pets` ( 
    `id` INT NOT NULL AUTO_INCREMENT , 
    `animalTypeId` INT NOT NULL , 
    `name` VARCHAR(100) NOT NULL , 
    `colorId` INT NOT NULL , 
  PRIMARY KEY (`id`), INDEX (`animalTypeId`), INDEX (`colorId`)
) ;

CREATE TABLE  IF NOT EXISTS `hobbies` ( 
    `id` INT NOT NULL AUTO_INCREMENT , 
    `hobbyTypeId` INT NOT NULL , 
    `hoursPerWeekSpend` INT NOT NULL , 
    `websiteUrl` VARCHAR(300) NULL , 
  PRIMARY KEY (`id`), INDEX (`hobbyTypeId`)
) ;

CREATE TABLE  IF NOT EXISTS `sports` ( 
    `id` INT NOT NULL AUTO_INCREMENT , 
    `sportTypeId` INT NOT NULL , 
    `hoursPerWeekSpend` INT NOT NULL , 
    `nameClub` VARCHAR(100) NULL , 
    `professional` TINYINT NOT NULL DEFAULT 0, 
  PRIMARY KEY (`id`), INDEX (`sportTypeId`)
) ;

CREATE TABLE  IF NOT EXISTS `professions` ( 
    `id` INT NOT NULL AUTO_INCREMENT , 
    `professionId` INT NOT NULL , 
    `hoursPerWeek` INT NOT NULL , 
    `nameCompany` VARCHAR(100) NULL , 
    `jobDescription` VARCHAR(400) NULL, 
  PRIMARY KEY (`id`), INDEX (`professionId`)
) ;


INSERT INTO `users` (`id`, `name`, `linkedTable`, `foreignId`) 
   VALUES 
   (NULL, 'Hank', 'pets', '1'), 
   (NULL, 'Peter', 'hobbies', '2'), 
   (NULL, 'Muhammed', 'professions', '1'), 
   (NULL, 'Clarice', NULL, NULL), 
   (NULL, 'Miryam', 'professions', '2'), 
   (NULL, 'Ming-Lee', 'hobbies', '1'), 
   (NULL, 'Drakan', NULL, NULL), 
   (NULL, 'Gertrude', 'sports', '2'), 
   (NULL, 'Mbase', NULL, NULL);


INSERT INTO `pets` (`id`, `animalTypeId`, `name`, `colorId`) 
VALUES (NULL, '1', 'Mimi', '3'), (NULL, '2', 'Tiger', '8');

INSERT INTO `hobbies` (`id`, `hobbyTypeId`, `hoursPerWeekSpend`, `websiteUrl`) 
VALUES (NULL, '123', '21', NULL), (NULL, '2', '1', 'http://www.freesoup.org');

INSERT INTO `sports` (`id`, `sportTypeId`, `hoursPerWeekSpend`, `nameClub`, `professional`) 
VALUES (NULL, '2', '3', 'Racket to Racket', '0'), (NULL, '12', '34', NULL, '1');

INSERT INTO `professions` (`id`, `professionId`, `hoursPerWeek`, `nameCompany`, `jobDescription`) 
VALUES (NULL, '275', '40', 'Ben & Jerry\'s', 'Ice cream designer'), (NULL, '21', '24', 'City of Dublin', 'Garbage collector');

然后运行第一个查询。

有趣的讨论笔记:如何索引它?

关于MYSQL - 一列引用多表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10843800/

相关文章:

php - 如何通过 php 中的 mysql 查询逐行迭代

php - 我在使用 PHP 将变量从 SQL 解析为另一个 SQL 语句时遇到问题

php - 从 mysql_fetch_assoc 返回并解析结果

sql - 为什么 SQL 全文索引不返回包含 # 的单词的结果?

mysql - 关于哪种方法更好的 SQL-(mysql) 问题

sql-server-2008 - 创建一个包含 View 的 View - 性能影响?

mysql - Wordpress MySQL 查询执行时间太长

mysql where 子句根据设备显示横幅

mysql - 按月对日志进行分组总计

mysql - 更新表中的数据设置特定日期的最小计时事件