MySQL DDL Trigger, схема таблицы различий для переименования столбцов - PullRequest
10 голосов
/ 15 декабря 2011

Я создаю скрипт PHP для сравнения схемы двух баз данных.

Мне удалось проверить изменения схемы в отношении удаленных / добавленных таблиц, столбцов, индексов, ссылок, но когда дело доходит до переименованных столбцов, я немного застрял.

В следующем примере исходная база данных содержит наиболее актуальную схему, а база назначения содержит аналогичную схему, но, вероятно, устарела.

Требования:

  • Мне не известно об изменениях, которые произошли со времени последнего различий.
  • Данные в базах данных не будут совпадать, но схема должна после различий.

Возьмем, к примеру, следующую схему в целевой базе данных.

Field   Type    Null    Key Default Extra
field1  int(11) NO      NULL     
field2  int(11) NO      NULL     
field3  int(11) NO      NULL     

А затем примите следующую схему в исходной базе данных.

Field   Type    Null    Key Default Extra
field1  int(11) NO      NULL     
field4  int(11) NO      NULL     
field3  int(11) NO      NULL     

Не зная явно, что произошло, я не могу определить, изменилось ли field2 на field4 с помощью DROP, ADD AFTER или CHANGE COLUMN. Следующие два запроса достигают одного и того же результата с точки зрения структуры таблицы, но данные теряются при использовании первого.

(1)    ALTER TABLE `demo` DROP `field2`
       ALTER TABLE `demo` ADD `field4` INT( 11 ) NOT NULL AFTER `field1` 

(2)    ALTER TABLE `demo` CHANGE `field2` `field4` INT( 11 ) NOT NULL 

Я, очевидно, могу отбросить старое имя столбца и создать новое, но тогда все исходные столбцы будут потеряны. Мне нужно использовать ALTER TABLE table CHANGE COLUMN field new_name structure; запрос вместо DROP column FROM table, за которым следует ALTER TABLE table ADD column definition;

Я надеялся, что смогу использовать триггер DDL для отслеживания изменений в схеме и вставки записи таких изменений в таблицу в исходной базе данных. Позже я мог бы запросить эту таблицу, чтобы определить, как появился определенный столбец. Однако, насколько я могу судить, невозможно запускать триггеры для запросов DDL в MySQL, что исключает регистрацию этих изменений. Я читал этот рабочий журнал ( WL # 2418: триггеры DDL ) в MySQL Forge (сейчас он находится в MySQL Developer Zone), но, к сожалению, его реализация еще не завершена.

Есть ли способ обновления таблиц в соответствии со схемой в отношении переименованных столбцов без потери данных?

Я смотрел на такие вещи, как MySQLDiff , но он должен быть встроен в существующий фрагмент кода, поэтому мне приходится создавать его самостоятельно.

Идеи, которые я рассмотрел

  • Добавьте комментарий к каждому столбцу, который является уникальным числом или строкой (для аргумента назовите его хешем). Запросите таблицу information_schema, чтобы получить это значение и сравнить его в каждом столбце. Если он уникален, то это новый столбец, или если он соответствует хешу, но не имени или структуре, он переименовывается / реконфигурируется.

  • Сравните схему, если есть новый столбец - проверьте его положение относительно соседних столбцов. Если имя нового столбца находится в той же позиции, что и отсутствующий, сравните структуру этого столбца. Если оно совпадает, считайте его переименованным. Если нет, считайте его удаленным, а затем добавленным.

Ответы [ 5 ]

1 голос
/ 10 января 2012

Я не думаю, что вы должны синхронизировать схему таким образом.Вы должны проверять сценарии миграции в исходном коде каждый раз, когда вы что-либо меняете, а затем в своей базе данных должна быть таблица, в которой регистрируется, какая миграция была применена.Таким образом, вы можете убедиться, что все миграции были применены ко всем базам данных.например `

CREATE TABLE `ddl_version` (
version` varchar(32)  NOT NULL,
`applied_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY `version` (`version`)

)`  
0 голосов
/ 23 декабря 2015

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

  1. Включить Общая запись в Mysql до table
  2. Теперь все запросы будут сохранены в mysql.general_log таблице.
  3. Теперь вы можете запустить запрос, подобный SELECT * FROM mysql.general_log WHERE argument LIKE 'ALTER%', чтобы получить все операторы SQL, которые относятся к модификации базы данных, включая переименования столбцов.

Надеюсь, это поможет ..

0 голосов
/ 10 августа 2012

MySQL не поддерживает триггеры DDL. Я вижу в их рабочем журнале, что они запланировали это для сервера 7.1.

Идентификатор задачи: WL # 2418.

0 голосов
/ 06 января 2012

Самая большая проблема здесь заключается в том, что если для одной и той же таблицы было изменено более 1 имени столбца (одного и того же типа), НЕТ способа определить, какой из столбцов был изменен на какой.(Тем не менее, существует возможность фактически сравнивать данные и надеяться, что некоторые данные одинаковы в обеих таблицах, и таким образом можно будет определить, какой столбец изменился на что, но это будет совершенно ненадежно)

Если есть также проблема изменения 1 (или более) поля и добавления 1 (или более), вы снова столкнетесь с той же проблемой, что и выше.

MySQLDiff, упомянутый выше, сможет сказатьВы, какие поля являются новыми, а какие старыми (и больше похожи на новые таблицы и т. д.), но он не сможет сказать вам, какое имя столбца изменилось на какое, и даже не пытается.(Ни одно программное обеспечение не может надежно сделать это, особенно если ваши данные не совпадают между базами данных). Вы можете увидеть, что он делает в: mysql-1.5.0 / library / database.lib.php и mysql-1.5.0 / library / generator.lib.php

Одна вещь, которую я бы настоятельно рекомендовал, - это представить очень простой процесс в вашей команде разработчиков.- Каждый раз, когда вносятся изменения в структуру БД (или любые записи, которые необходимы для работы системы), должны быть записаны, например, в.Файл db_changes.sql, который находится под контролем версий.Для каждой новой ревизии, если такие изменения в db необходимы, файл db_changes.sql стирается, изменения записываются и сохраняются как новая ревизия.Таким образом, изменения в структуре базы данных корректируются должным образом, и их применение - это всего лишь вопрос различий между двумя точками пересмотра.(MysqlWorkbench - один из клиентов, который, если вы измените таблицы, покажет вам запрос, который он будет выполнять внутри, если ваши разработчики вообще будут использовать клиента)

0 голосов
/ 03 января 2012
ALTER TABLE table
 CHANGE COLUMN old_col_name
 new_col_name column_definition;

Это изменяет имя столбца без потери данных в столбце (если только вы не измените тип данных, а новый тип данных не будет меньше старого типа данных, например, изменив BIGINT на SMALLINT).

Эта команда, к сожалению, требует, чтобы вы повторили текущее определение столбца, например, тип данных, NOT NULL и другие параметры.В MySQL нет команды просто переименовать столбец.

Предложение CHANGE COLUMN является расширением MySQL для стандартного SQL, в котором нет синтаксиса для переименования столбца на месте.

Другое решение, если вы хотите придерживаться стандартного SQL, - это добавить новый столбец, скопировать данные из старого столбца в новый столбец и затем удалить старый столбец:

ALTER TABLE table ADD COLUMN new_col_name column_definition;

UPDATE table SET new_col_name = old_col_name;

ALTER TABLE table DROP COLUMN old_col_name;
...