【问题标题】:List database table relationships and their type列出数据库表关系及其类型
【发布时间】:2017-06-30 22:42:39
【问题描述】:

我想知道是否有一种方法可以根据外键关系以编程方式列出数据库中的表关系及其类型?


以这些表格为例:

CREATE TABLE `a` (
    `id` int NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB;

CREATE TABLE `b` (
    `id` int NOT NULL,
    `a_id` int NOT NULL,
    PRIMARY KEY (`id`),
    CONSTRAINT `fk.b.a.b` FOREIGN KEY (`a_id`) REFERENCES `a` (`id`)
) ENGINE=InnoDB;

CREATE TABLE `c` (
    `id` int NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB;

CREATE TABLE `b_c` (
    `b_id` int NOT NULL,
    `c_id` int NOT NULL,
    PRIMARY KEY (`b_id`,`c_id`),
    CONSTRAINT `fk.b_c.b.c` FOREIGN KEY (`c_id`) REFERENCES `c` (`id`),
    CONSTRAINT `fk.b_c.c.b` FOREIGN KEY (`b_id`) REFERENCES `b` (`id`)
) ENGINE=InnoDB;

我们可以通过这个查询得到外键关系:

SELECT 
    table_name 'table',
    column_name 'column',
    referenced_table_name 'referenced_table',
    referenced_column_name 'referenced_column'
    FROM
        information_schema.key_column_usage
    WHERE
        referenced_table_name IS NOT NULL
        AND table_schema = 'test';

table   column   referenced_table   referenced_column
b       a_id     a                  id
b_c     c_id     c                  id
b_c     b_id     b                  id

现在...我认为上面的关系信息应该足以推断存在哪些关系及其类型,但我无法将其翻译成算法...回答我原来的问题:我知道有办法,但一直找不到。 ????

所以,我希望比我这里更聪明的人知道如何已经做到这一点,或者准备好脑筋急转弯(在我的情况下是脑杀手)来解决? ????


基本上,在这种情况下,“答案”应该是有 4 个关系:

  • A → B,一对多
  • B → A,多对一
  • B → C,多对多,通过 b_c
  • C → B,多对多,通过 b_c

我需要在 PHP 中执行此操作,但任何可理解的算法/伪代码也有望提供很大帮助。 ??????????

【问题讨论】:

  • 我不认为这是重复的
  • @Marc-AntoineParent ,这是我发现的 许多 其他帖子之一(在一个或另一个变体中)我在帖子中的 SQL。我的问题是关于“下一步”,即如何将来自该SQL的响应“解析”到我最后列出的关系类型信息中。
  • @Svish 好的,很抱歉 :) 您需要以图形方式表示关系还是只列出它们?
  • @Marc-AntoineParent 我只需要将它们放在一个列表中,以便稍后在我的代码中使用这些信息。例如,给定b,我需要知道它有一个与a 的多对一以及与cb_c 的多对多。

标签: php mysql sql mariadb relationships


【解决方案1】:

我认为one to many 很简单,您已经掌握了。遍历这个表

row table   column   referenced_table   referenced_column
1   b       a_id     a                  id
2   b_c     c_id     c                  id
3   b_c     b_id     b                  id

你有所有的one to many

  • 第 1 行:A → B,一对多
  • 第 2 行:C → B_C,一对多
  • 第 3 行:B → B_C,一对多

所有的many to one 都是这些的倒置

  • 第 1 行:B → A,多对一(前一个相反)
  • 第 2 行:B_C → C,多对一(之前的反转)
  • 第 3 行:B_C → B,多对一(之前的反转)

困难在于找到many-to-many,理论上我认为您应该使用图表并导航它以查找所有many-to-many 关系,但我可以想到您可以使用您拥有的表格制作的技巧:组按这样的列表

SELECT
    table as through,
    GROUP_CONCAT(referenced_table SEPARATOR ',') as tables
FROM (
    SELECT 
        table_name 'table',
        referenced_table_name 'referenced_table',
    FROM
        information_schema.key_column_usage
    WHERE
        referenced_table_name IS NOT NULL
        AND table_schema = 'test';
    ) as yourQuery
GROUP BY table
HAVING count(referenced_table) > 1;

你应该以这样的方式结束

row   through   tables
1     b_c       c,b

它会在第一列中为您提供直通表的名称,以及“表”行上的多个多对多表的名称(可能是 2 个或更多)

【讨论】:

  • 整洁!这不包括哪些情况?我在考虑 A → C 类型的关系,但实际上并不需要那些准备好的信息,甚至不确定这种关系会被称为什么......但是,任何情况下都没有包含在简单的双边关系中?跨度>
  • 我在想像A → B → C ← D这样的情况,你可能想知道A和D之间的关系(通过B和C多对多?)以及像A → A这样的循环情况,或A → B → A...等。我认为所有这些都可以通过创建关系图然后遍历它来解决。我给出的解决方案只适用于一级关系,二级多对多通
  • 啊哈,对。认为我(希望)不会遇到太复杂的案例,并且认为我目前需要的只是那些一级和二级多对多通。并且认为如果我首先使用您的 SQL 获取多对多,然后按照您在开始时所说的操作,我现在就可以获取它们,只是过滤掉 through 表,因为我不想要他们列出来。一旦我有了这个,我想我可以通过“遍历”数据来找到那些“进一步”的关系?猜猜这实际上可能是在做那个图表的事情?
  • 图表是指en.wikipedia.org/wiki/Graph_(abstract_data_type) 遍历是指en.wikipedia.org/wiki/Graph_traversal 这些是复杂的算法和数据结构。我不知道这些“进一步”的关系在哪种情况下可能有用,我只是指出,如果你需要它们,这对你来说可能是个问题。你也可以“走”数据,这有点像做图表,只是不是更好的解决方案。如果你要“走路”,也要小心不要陷入像A → B → C → A → B → C → A → ...这样的循环中
  • 啊,没错。好吧,是的,在我的情况下,我不需要那些“进一步”的。如此甜蜜!我将使用这个 SQL,看看我是否可以现在在我的 PHP 项目中构建我需要的信息,我想我现在实际上可能能够做到,非常感谢! ?
【解决方案2】:
USE information_schema;
SELECT * FROM `REFERENTIAL_CONSTRAINTS`;
SELECT * FROM `TABLE_CONSTRAINTS` where constraint_type LIKE 'F%';
SELECT * FROM `INNODB_SYS_FOREIGN_COLS`;
SELECT * FROM `INNODB_SYS_FOREIGN`;

这是我在 5.6 和 MariaDB 10.2.2 上发现的。

对于 many:many 表,您不妨同时走两个方向。 Tips.

【讨论】:

  • 还有,我的问题是,您将如何使用它来提取我在帖子末尾列出的信息?
  • 我的直觉说你无法完全实现它,特别是如果 FK 不是精确创建的。此外,FK 与“现实世界”不匹配的情况也很多;看看这个论坛上关于 FK 的问题数量。
  • OTOH 有很多绘图包可以合理地绘制图片。
  • 在这种情况下,FK 是(至少应该)精确创建的,并且与现实世界相匹配,因为我是创建它们的人?而且我不需要图片,我需要信息/数据,以便我可以在我的代码中使用它。
猜你喜欢
  • 2022-01-06
  • 1970-01-01
  • 2019-03-08
  • 1970-01-01
  • 2011-07-12
  • 2015-10-14
  • 1970-01-01
  • 2019-02-25
  • 1970-01-01
相关资源
最近更新 更多