Этот запрос выбирает все имена таблиц из указанной базы данных и показывает их уровень в дереве внешних ключей.
WITH RECURSIVE
cte1 AS
(
SELECT table_name,
referenced_table_name
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE table_schema = 'test'
AND referenced_column_name IS NOT NULL
),
cte2 AS
(
SELECT t1.referenced_table_name name, 1 level
FROM cte1 t1
WHERE NOT EXISTS (
SELECT NULL
FROM cte1 t2
WHERE t1.referenced_table_name = t2.table_name
)
UNION ALL
SELECT cte1.table_name, cte2.level + 1
FROM cte1
JOIN cte2 ON cte1.referenced_table_name = cte2.name
WHERE cte2.level <= (
SELECT COUNT(*)
FROM cte1
)
)
SELECT name, MIN(level) level
FROM cte2
GROUP BY name
ORDER BY name, level;
При повторном создании структуры базы данных или копировании данных из исходной базы данных в ее воссозданную копию необходимо обработать таблицы в указанном порядке.
При удалении таблиц вы должны делать это в обратном порядке.
В нормальном состоянии максимальное level
значение не может превышать количество таблиц . Но возможно, что в структуре базы данных существует ссылочное кольцо. В таком случае максимальное level
значение будет больше, чем количество таблиц, а вся техника неприменима .
В вашем конкретном случае вы:
- Выполните этот запрос (не забудьте заменить
WHERE table_schema = 'test'
вашим реальным именем базы данных). - Создать новую базу данных.
- Для каждой строки в выводе (сохранение порядка) выполнить команду
CREATE TABLE new_database.{name} LIKE old_database.{name} ;
Для каждой строки на выходе, где
level = 1
выполнить команду
INSERT INTO new_database.{name}
SELECT * FROM old_database.{name} LIMIT {some_value};
some_value
может быть одинаковым для всех root таблиц или отдельных.
Для каждой строки на выходе, где
level > 1
выполнить команду
INSERT IGNORE INTO new_database.{name}
SELECT * FROM old_database.{name} LIMIT {some_value};
Наслаждайтесь.
Если схема содержит триггеры, они должны быть зарезервированы отдельно и восстановлены в новую базу данных в качестве последнего шага.