MySQL比较数据库并添加缺少的列

时间:2015-06-26 18:24:59

标签: mysql

我有两个非常大的数据库,几乎每个方面都相同但是每个表中有很多额外的列,而第二个没有。

将行保留为默认值我将如何比较表并将第一个数据库中定义的缺失列添加到第二个数据库?

实施例: 数据库1(id,name,surname,extra) 数据库2(id,name,surname)

我想添加额外的'数据库1到数据库2中定义的列。

我不太关心实际的额外数据,可以将其设置为数据库1中定义的默认值。这些列都是需要的。

请注意:我已经尝试过Toad等工具,但是他们都希望更改第二个数据库中的数据以匹配我不想要的第一个数据。

数据库1示例表(CollectionSearchIndexAttributes):

CREATE TABLE IF NOT EXISTS `CollectionSearchIndexAttributes` (
  `cID` int(10) unsigned NOT NULL DEFAULT '0',
  `ak_meta_title` longtext COLLATE utf8_unicode_ci,
  `ak_meta_description` longtext COLLATE utf8_unicode_ci,
  `ak_meta_keywords` longtext COLLATE utf8_unicode_ci,
  `ak_icon_dashboard` longtext COLLATE utf8_unicode_ci,
  `ak_exclude_nav` tinyint(1) DEFAULT '0',
  `ak_exclude_page_list` tinyint(1) DEFAULT '0',
  `ak_header_extra_content` longtext COLLATE utf8_unicode_ci,
  `ak_tags` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `ak_is_featured` tinyint(1) DEFAULT '0',
  `ak_exclude_search_index` tinyint(1) DEFAULT '0',
  `ak_exclude_sitemapxml` tinyint(1) DEFAULT '0',
  `ak_job_posting_department` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `ak_job_location` longtext COLLATE utf8_unicode_ci,
  `ak_exclude_subpages_from_nav` tinyint(1) DEFAULT '0',
  `ak_thumbnail` int(11) DEFAULT '0',
  `ak_blog_entry_topics` longtext COLLATE utf8_unicode_ci,
  `ak_project_topics` longtext COLLATE utf8_unicode_ci,
  `ak_project_client` longtext COLLATE utf8_unicode_ci,
  `ak_project_tasks` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `ak_project_skills` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`cID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

数据库2示例表(CollectionSearchIndexAttributes):

CREATE TABLE IF NOT EXISTS `CollectionSearchIndexAttributes` (
  `cID` int(10) unsigned NOT NULL DEFAULT '0',
  `ak_meta_title` longtext COLLATE utf8_unicode_ci,
  `ak_meta_description` longtext COLLATE utf8_unicode_ci,
  `ak_meta_keywords` longtext COLLATE utf8_unicode_ci,
  `ak_icon_dashboard` longtext COLLATE utf8_unicode_ci,
  `ak_exclude_nav` tinyint(1) DEFAULT '0',
  `ak_exclude_page_list` tinyint(1) DEFAULT '0',
  `ak_header_extra_content` longtext COLLATE utf8_unicode_ci,
  `ak_tags` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `ak_is_featured` tinyint(1) DEFAULT '0',
  `ak_exclude_search_index` tinyint(1) DEFAULT '0',
  `ak_exclude_sitemapxml` tinyint(1) DEFAULT '0',
  PRIMARY KEY (`cID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

正如您所看到的,数据库1的表有8列,数据库2的表没有。

2 个答案:

答案 0 :(得分:2)

这是您可以使用的过程,只需根据db名称进行更新。 另外,我在这里假设所有表都存在于dbs中。

这是两个样本表

mysql> select table_name, column_name
    -> from information_schema.columns 
    -> where table_schema = 'db1'
    -> order by table_name
    -> ;
+------------+-------------+
| table_name | column_name |
+------------+-------------+
| t1         | c1          |
| t1         | c2          |
| t2         | c1          |
| t2         | c2          |
| t2         | c3          |
| t3         | c1          |
| t3         | c2          |
| t3         | c3          |
+------------+-------------+
8 rows in set (0.00 sec)

mysql> 
mysql> select table_name, column_name
    -> from information_schema.columns 
    -> where table_schema = 'db2'
    -> order by table_name
    -> ;
+------------+-------------+
| table_name | column_name |
+------------+-------------+
| t1         | c1          |
| t2         | c1          |
| t2         | c2          |
+------------+-------------+
3 rows in set (0.00 sec)

这是程序

drop procedure sync_tables;

delimiter //
create procedure sync_tables()
begin

declare tab_name  VARCHAR(100);
declare col_name  VARCHAR(100);
declare col_type  VARCHAR(100);

declare sql_cmd  VARCHAR(100);

declare done int default FALSE;

declare cur cursor for 
select concat('alter table ' , 'db2','.',table_name, ' add column ', column_name , ' ' , column_type ) as sql_cmd_c
  from information_schema.columns
  where table_schema = 'db1' 
     and
          concat( table_name, '_', column_name) not in (
              select concat( table_name,'_',column_name) as db2p
              from information_schema.columns   
              where table_schema = 'db2'
);
declare continue handler for not found  set done = TRUE;
read_loop : LOOP
   open cur;
   fetch cur into sql_cmd;
     set @sqlcmd := sql_cmd;
     prepare sqlcmd from @sqlcmd;
     execute sqlcmd;
     if done then 
        leave read_loop;
     end if;
     select 'bhavin';
end LOOP;

end//
delimiter ;

这是运行调用后的更新表

mysql> select table_name, column_name
    -> from information_schema.columns 
    -> where table_schema = 'db1'
    -> order by table_name
    -> ;
+------------+-------------+
| table_name | column_name |
+------------+-------------+
| t1         | c1          |
| t1         | c2          |
| t2         | c1          |
| t2         | c2          |
| t2         | c3          |
| t3         | c1          |
| t3         | c2          |
| t3         | c3          |
+------------+-------------+
8 rows in set (0.00 sec)

mysql> 
mysql> select table_name, column_name
    -> from information_schema.columns 
    -> where table_schema = 'db2'
    -> order by table_name
    -> ;
+------------+-------------+
| table_name | column_name |
+------------+-------------+
| t1         | c1          |
| t1         | c2          |
| t2         | c1          |
| t2         | c2          |
| t2         | c3          |
+------------+-------------+
5 rows in set (0.00 sec)

答案 1 :(得分:0)

我不知道有什么工具可以做到这一点,但使用某些脚本很容易。

在MYSQL中,数据库有一个隐式INFORMATION_SCHEMA,其中包含有关该数据库中其他表的信息。

您可以使用

加入表格
SELECT c1.table_name, c1.column_name
FROM db_1.INFORMATION_SCHEMA.columns c1 LEFT JOIN
    db_2.INFORMATION_SCHEMA.columns c2
      ON  c1.table_name = c2.table_name AND c1.column_name = c2.column_name
WHERE c2.column_name IS NULL

这假设db_1是第一个,db_2是第二个。

这将有助于查找列,然后您可以轻松添加缺少的列。