【发布时间】:2012-01-21 02:52:48
【问题描述】:
我正在创建一个 PHP 脚本来比较两个数据库的架构。
我已经设法检查有关删除/添加的表、列、索引、引用的架构更改,但是当涉及到重命名的列时,我有点卡住了。
在以下示例中,源数据库包含最新的架构,而目标数据库包含类似的架构但可能已过时。
先决条件:
- 我不知道自上次差异以来发生的变化。
- 数据库中的数据将不匹配,但架构应该在 diff 之后。
以目标数据库中的以下架构为例。
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 是否通过DROP, ADD AFTER 或CHANGE COLUMN 更改为field4。以下两个查询在表结构方面实现了相同的结果,但是使用前者会丢失数据。
(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 触发器来跟踪架构中的更改并将此类更改的记录插入到源数据库中的表中。稍后我可以查询此表以确定某个列是如何形成的。但是,据我所知,不可能在 MySQL 中的 DDL 查询上运行触发器,从而排除记录这些更改的可能性。我在 MySQL Forge(现在位于 MySQL 开发者专区)上阅读了这个工作日志 (WL#2418: DDL Triggers),但不幸的是,它似乎仍在等待实施。
有没有一种方法可以更新表以匹配关于重命名列的架构而不会丢失数据?
我看过MySQLDiff 之类的东西,但它需要内置到现有的代码中,所以我必须自己构建它。
我考虑过的想法
为每一列添加一个注释,它是一个唯一的数字或字符串(为了参数,将其称为哈希)。查询 information_schema 表以检索此值并在每一列上进行比较。如果它是唯一的,那么它就是一个新列,或者如果它匹配一个哈希而不是一个名称或结构,那么它就被重命名/重新配置了。
比较架构,如果有新列 - 检查它相对于相邻列的位置。如果新列的名称与缺少的列的名称相同,则比较该列的结构。如果匹配,请考虑将其重命名。如果没有,请考虑将其删除然后添加。
【问题讨论】:
-
当您使用 PHP 脚本比较方案时,我不明白为什么您在谈论触发器,因此您现在在检测到差异时可以使用更改或添加列执行以下解决方案,复制数据等
-
我不知道该列是否被重命名或删除,并在其位置添加了另一个。如果前者是真的,那么我可以使用 Bill Karwin 的第一个解决方案,如果后者是真的,那么我可以使用他的第二个解决方案。问题是我不知道架构差异的原因。这意味着我不能在删除旧列之前随意将数据复制到新列中,因为它们可能不相关。我更新了我的问题,试图更清楚地解释我的问题。
-
我猜你控制了这两个数据库?让两个数据库具有相同数据的目的是什么。是测试环境还是复制?
-
用于将测试环境复制到多个实时数据库。我控制着这两个数据库,但主数据库上有多个开发人员,并且目前大约有 10-15 个不同的目标数据库,它们都具有不同的架构。
-
好的,我曾经使用过一个设置,其中我们有一个来自实时服务器的主要测试环境,它使用 mysql 复制,然后是一个 PHP 设置,以轻松删除开发人员的数据库并从主要测试环境中复制它。但我不知道您的数据库有多大,是否有可能
标签: php mysql triggers diff alter-table