Mysql: Скопировать структуру таблицы, включая внешние ключи
Я знаю, как скопировать таблицу с помощью create new_table like old_table
, но это также не копирует ограничения внешних ключей. Я также могу выполнять строковые манипуляции с результатом show create table old_table
(с использованием регулярных выражений для замены имени таблицы и имен ограничений внешнего ключа), но это кажется склонным к ошибкам. Есть ли лучший способ скопировать структуру таблицы, включая внешние ключи?
Ответы
Ответ 1
Возможно, вы могли бы написать процедуру, которая после create table like
готовит инструкции ALTER TABLE ...
на основе информации из:
SELECT *
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_NAME LIKE '<table_name>'
AND TABLE_SCHEMA = '<db_name>'
AND REFERENCED_TABLE_NAME IS NOT NULL;
Ответ 2
Ответ Wrikken вдохновил меня. Позвольте мне расширить его.
Ну, все сложнее. Смотрите: http://dev.mysql.com/doc/refman/5.1/en/create-table.html. В нем говорится, что будут проблемы с таблицами TEMPORARY
и другими вещами. Решение, упомянутое Wrikken, является хорошим подходом, однако для получения информации о правилах UPDATE
и DELETE
вам потребуется, по крайней мере, еще один поиск:
SELECT *
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE TABLE_NAME LIKE '<table_name>'
AND CONSTRAINT_SCHEMA = '<db_name>';
Итак, может быть хорошей идеей получить инструмент, который упростит задачу. Я лично использую Adminer (https://sourceforge.net/projects/adminer/). Он поставляется с возможностью экспорта всей БД (со всеми таблицами, триггерами, внешними ключами...). После его экспорта (в синтаксисе SQL) вы можете легко изменить имя базы данных и импортировать ее обратно. Я написал об этом в разделе ошибок в проекте (см. Билет 380).
Возможно, у вас уже есть ваш любимый менеджер БД и вы не хотите другого. Вы можете выполнить следующие шаги:
- Дамп БД с помощью
mysqldump
→ вы получаете file.sql
- Создать новую БД
- Выполнить
file.sql
в новой БД
Оба Adminer
и mysqldump
имеют возможность выбирать только определенные таблицы, поэтому вам не нужно экспортировать всю БД. Если вам нужна только структура, а не данные, используйте опцию -d
для mysqldump
или щелкните ее в Adminer
.
Ответ 3
Если немного скриптов в стороне, вы можете использовать SHOW CREATE TABLE
в нескольких строках вроде этого (PHP, но концепция работает на любом языке):
// Get the create statement
$retrieve = "SHOW CREATE TABLE <yourtable>";
$create = <run the $retrieve statement>
// Isolate the "Create Table" index
$create = $create['Create Table'];
// Replace old table name with new table name everywhere
$create = preg_replace("/".$newname."/", $oldname, $create);
// You may need to rename foreign keys to prevent name re-use error.
// See http://stackoverflow.com/questions/12623651/
$create = preg_replace("/FK_/", "FK_TEMP_", $create);
// Create the new table
<run the $create statement>
Не очень элегантный, но он работает до сих пор. Я делаю это в тестовой среде, поэтому я помещаю это в свой метод setUp()
.
Ответ 4
Если у вас есть phpMyAdmin, вы можете экспортировать только структуру своей таблицы, а затем изменить старые имена таблиц на новые в вашем .sql файле и импортировать обратно.
Это довольно быстрый способ
Ответ 5
Я создал скрипт bash для копирования таблицы в другую базу данных, модифицируя ключи и ограничения, добавляя к ним '_1':
mysqldump -h ${host_ip} -u root -p${some_password} ${some_database} ${some_table} > some_filename
sed -i -r -e '[email protected] '([a-zA-Z0-9_]*)'@KEY '\1_1'@g' -e '[email protected] '([a-zA-Z0-9_]*)'@CONSTRAINT '\1_1'@g' some_filename
mysql -h ${host_ip} -u root -p${some_password} ${some_new_database} < some_filename
Это работает и для новых экземпляров базы данных, но команда sed не понадобится. Это необходимо, только если исходная и целевая базы данных находятся в одном и том же экземпляре.
Ответ 6
Если вы просто хотите очистить таблицу, вы можете скопировать все соответствующие данные в таблицу копирования. Затем обрезайте и скопируйте обратно. Результат состоит в том, что ваш FK сохранен.
CREATE TABLE IF NOT EXISTS t_copy LIKE t_origin;
INSERT INTO t_copy
SELECT t_origin.*
FROM t_origin;
SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE t_origin;
INSERT INTO t_origin
SELECT t_copy.*
FROM t_copy;
DROP TABLE t_copy;
SET FOREIGN_KEY_CHECKS = 1;