简体   繁体   中英

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:

  • A → B, one-to-many
  • B → A, many-to-one
  • B → C, many-to-many, through b_c
  • C → B, many-to-many, through b_c

I need to do this in PHP, but any sort of understandable algorithm/pseudo code would hopefully help a lot too. 👍🏼

I think the one to many is easy, you already got it. 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

  • row 1: A → B, one-to-many
  • row 2: C → B_C, one-to-many
  • row 3: B → B_C, one-to-many

and all the many to one are the reversed of those

  • row 1: B → A, many-to-one (reverse of previous)
  • row 2: B_C → C, many-to-one (reverse of previous)
  • row 3: B_C → B, many-to-one (reverse of previous)

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

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)

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.

For a many:many table, you may as well go both directions simultaneously. Tips .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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