2017-02-13 17 views
0

Мне интересно, есть ли способ программно перечислить отношения в базе данных в базе данных и их тип, основанный на отношениях внешнего ключа?Перечислите отношения базы данных базы данных и их тип


Возьмем, к примеру эти таблицы:

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 

сейчас ... Я думаю, взаимосвязи информации выше должно быть достаточно, чтобы вывести, что rel существует и их типы, но я не могу перевести его в алгоритм ... Чтобы ответить на мой первоначальный вопрос: я знаю, что есть способ, но не смог его найти.

Итак, я надеюсь, что кто-то более яркий, чем я здесь, либо знаю, как это можно сделать уже, либо для мозгового дразнилки (мозгового убийцы, в моем случае), чтобы решить?


В принципе, "ответ" должен, в этом случае в том, что есть 4 отношения:

  • → B, один-ко-многим
  • B → A, многоэлектронные к-одному
  • B → C, многие-ко-многим, через b_c
  • C → B, многие-ко-многим, через b_c

Мне нужно сделать это на PHP, но любой вид понятного алгоритма/псевдокода, надеюсь, тоже поможет.

+0

Возможный дубликат: http://stackoverflow.com/questions/20855065/how-to-find-all-the-relations-between-all-mysql-tables –

+0

Я не думаю, что это дубликат – jperelli

+0

@ Marc-AntoineParent ** Нет **, это одно из * многих * других сообщений, которые я нашел, где ответ (в том или ином варианте) SQL, который у меня есть в моем сообщении. Мой вопрос касается «следующего шага», то есть как «разобрать» ответ * из * этого SQL в информацию типа отношения, которую я перечисляю в конце. – Svish

ответ

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, teoretically Я думаю, вы должны использовать график и ориентироваться в ней, чтобы найти все 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 

Wich даст вам имя через стол в первом столбце, а имя множества многих ко многим таблицам на «таблицы» (могут быть 2 или более)

+0

Аккуратно! В каких случаях это не распространяется? Я думаю, что отношения типа A → C, но на самом деле не нуждаются в этой информации в готовом виде, и не уверены, что бы эти отношения были названы даже ... Но, какие случаи не охватываются простыми двусторонними отношениями? – Svish

+0

Я думаю о таком случае, как этот «A → B → C ← D», вы можете знать связь между A и D (многие ко многим через B и C?), А также циклические случаи, такие как A → A ', или' A → B → A' ... и т. д. Я думаю, что все это можно было бы решить, создав граф отношений и затем пройдя его. Решение, которое я дал только для отношений первой степени, и второй степени много-много-через – jperelli

+0

Ага, справа. Думаю, что я (надеюсь) не выберет слишком сложные случаи, и думаю, что все, что мне нужно сейчас, - это те, кто находится в первой и второй степени.И подумайте, что я смогу получить их сейчас, если сначала я использую ваш SQL, чтобы получить много-ко-многим, а затем сделайте то, что вы сказали в начале, просто отфильтровывая таблицы 'through', поскольку я не хочу их перечислены. И как только у меня есть это, я полагаю, что я мог бы найти эти «дальнейшие» отношения путем «ходьбы» данных? Угадайте, что на самом деле может быть что-то вроде этого графа? – Svish

0
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.

Для многих: множество таблиц, вы также можете идти в оба направления одновременно. Tips.

+0

И, мой вопрос, как бы вы использовали это, чтобы извлечь информацию, указанную в конце моего сообщения? – Svish

+0

My Gut говорит, что вы не можете достичь этого полностью, особенно если FK не созданы точно. Кроме того, есть много случаев, когда FK не соответствуют «реальному миру»; просто посмотрите на количество вопросов на этом форуме о FKs. –

+0

OTOH есть много пакетов для рисования, которые делают разумную работу по покраске картин. –