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:
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
and all the many to one
are the reversed of those
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.