MySQL DDL Trigger,用于列重命名的Diff表模式

Ben*_*rne 10 php mysql diff triggers alter-table

我正在创建一个PHP脚本来比较两个数据库的模式.

我已经设法检查有关删除/添加的表,列,索引,引用的架构更改,但是当涉及到重命名的列时,我有点卡住了.

在以下示例中,源数据库包含最新的模式,目标数据库包含类似的模式,但可能已过期.

先决条件:

  • 我不知道自上次差异以来发生的变化.
  • 数据库中的数据不匹配,但架构应该在diff之后.

以目标数据库中的以下模式为例.

Field   Type    Null    Key Default Extra
field1  int(11) NO      NULL     
field2  int(11) NO      NULL     
field3  int(11) NO      NULL     
Run Code Online (Sandbox Code Playgroud)

然后在源数据库中假设以下模式.

Field   Type    Null    Key Default Extra
field1  int(11) NO      NULL     
field4  int(11) NO      NULL     
field3  int(11) NO      NULL     
Run Code Online (Sandbox Code Playgroud)

不知道什么明确发生,我无法确定是否field2改为field4途经DROP, ADD AFTERCHANGE 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 
Run Code Online (Sandbox Code Playgroud)

我显然可以删除旧列名并创建一个新列,但然后丢失原始列中的任何数据.我需要使用ALTER TABLE table CHANGE COLUMN field new_name structure;查询而不是DROP column FROM table后跟ALTER TABLE table ADD column definition;

我希望我可以使用DDL触发器来跟踪架构中的更改,并将此类更改的记录插入源数据库中的表中.我以后可以查询此表以确定某个列是如何形成的.但是,据我所知,它不可能在MySQL中运行DDL查询的触发器,这会排除记录这些更改.我在MySQL Forge上阅读了这个工作日志(WL#2418:DDL触发器)(现在驻留在MySQL Developer Zone中),但它仍然不幸地显示为待执行.

有没有一种方法可以更新表以匹配关于重命名列而没有数据丢失的模式?

我已经看过像MySQLDiff这样的东西,但它需要构建到现有的代码中,所以我必须自己构建它.

我考虑过的想法

  • 为每个列添加注释,这是一个唯一的数字或字符串(为了参数,将其称为哈希).查询information_schema表以检索此值并在每列上进行比较.如果它是唯一的那么它是一个新列,或者如果它匹配一个哈希而不是一个名称或结构,那么它就被重命名/重新配置.

  • 比较模式,如果有新列 - 检查它相对于相邻列的位置.如果新列的名称与缺少的列的名称相同,则比较该列的结构.如果匹配,请考虑重命名.如果没有,请考虑删除然后添加.

Bil*_*win 0

ALTER TABLE table
 CHANGE COLUMN old_col_name
 new_col_name column_definition;
Run Code Online (Sandbox Code Playgroud)

这会更改列名称,而不会丢失列中的数据(除非您也更改数据类型并且新数据类型小于旧数据类型,例如将 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;
Run Code Online (Sandbox Code Playgroud)