简体   繁体   English

列出数据库表关系及其类型

[英]List database table relationships and their type

I'm wondering if there is a way to programmatically list table relationships in a database, and their type, based on foreign key relationships? 我想知道是否有一种方法可以基于外键关系以编程方式列出数据库中的表关系及其类型?


Take for example these tables: 以这些表为例:

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;

We can get the foreign key relationships with this query: 我们可以通过以下查询获取外键关系:

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

Now... I think the relationship information above should be enough to deduce what relationships exists and their types, but I'm not able to translate it into an algorithm... To answer my original question: I know there is a way, but haven't been able to find it. 现在...我认为上面的关系信息应该足以推断出存在的关系及其类型,但是我无法将其转换为算法...要回答我的原始问题:我知道有一种方法,但一直找不到。 😕 😕

So, I'm hoping someone more brilliant than I here either knows how one could do this already, or were up for a brain teaser (brain killer, in my case) to solve? 因此,我希望比我这里更聪明的人或者已经知道如何做到这一点,或者正在寻求解决难题(就我而言,是杀脑剂)? 🤔 🤔


Basically, the "answer" should, in this case, be that there are 4 relationships: 基本上,在这种情况下,“答案”应为4种关系:

  • A → B, one-to-many A→B,一对多
  • B → A, many-to-one B→A,多对一
  • B → C, many-to-many, through b_c B→C,通过b_c多对多
  • C → B, many-to-many, through b_c C→B,通过b_c多对多

I need to do this in PHP, but any sort of understandable algorithm/pseudo code would hopefully help a lot too. 我需要在PHP中执行此操作,但是任何一种可以理解的算法/伪代码也有望对您有所帮助。 👍🏼 👍🏼

I think the one to many is easy, you already got it. 我认为one to many很容易,您已经知道了。 Iterate through this table 遍历此表

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

and there you have all the one to many 那里有one to many

  • row 1: A → B, one-to-many 第1行:A→B,一对多
  • row 2: C → B_C, one-to-many 第2行:C→B_C,一对多
  • row 3: B → B_C, one-to-many 第3行:B→B_C,一对多

and all the many to one are the reversed of those 而且所有这些many to one

  • row 1: B → A, many-to-one (reverse of previous) 第1行:B→A,多对一(与上一相反)
  • row 2: B_C → C, many-to-one (reverse of previous) 第2行:B_C→C,多对一(上一相反)
  • row 3: B_C → B, many-to-one (reverse of previous) 第3行:B_C→B,多对一(与上一个相反)

The difficulty would be to find the many-to-many , teoretically I think you should use a graph and navigate it to find all many-to-many relations, but I can think of a trick you could make with the table you have: group by column table like this 困难在于查找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;

You should end with something like this 你应该以这样的结尾

row   through   tables
1     b_c       c,b

wich would give to you the name of the through-table in the first column, and the name of the multiple many-to-many tables on the "tables" row (could be 2 or more) 这将在第一栏中为您提供直通表的名称,并在“表”行中提供多个多对多表的名称(可以是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`;

That's what I found on 5.6 and MariaDB 10.2.2. 这就是我在5.6和MariaDB 10.2.2上发现的。

For a many:many table, you may as well go both directions simultaneously. 对于多对多表,您最好同时进行两个方向的操作。 Tips . 温馨提示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM