【问题标题】:MySQL query to show difference between development and production schemaMySQL 查询以显示开发和生产模式之间的差异
【发布时间】:2011-08-05 12:42:46
【问题描述】:

我想使用 MySQL 中的模式数据库进行查询
这显示了两个数据库模式之间的列、触发器和存储过程之间的区别:生产和开发。

查询,而不是工具
我见过Compare two MySQL databases
其中列出了可以执行此任务的工具,但我想知道是否有可以执行此任务的 查询
请只提出疑问,我真的不想了解工具、命令行黑客等。

我正在查看生产数据库和开发数据库是否不同步。
以及添加或更改了哪些字段、过程等,因此如果我推出使用数据库的客户端软件的新更新,我可以更新生产数据库。

我使用的是 MySQL 5.1 最新版本。

【问题讨论】:

  • 您是在谈论比较可能是相似数据库的表(例如生产与开发),并且希望由于任何变化而使它们同步?如果是这样,这就是为什么您想知道新的/更改的列、过程、索引等?否则,如果您尝试比较 ex: Maps data to Music to Movies...
  • 是的,开发和生产数据库之间的比较

标签: mysql schema information-schema


【解决方案1】:

约翰,试着运行这个脚本。在脚本开头指定要在变量中比较的两个数据库。查询返回数据集,并为表/视图列设置状态。

状态“仅在源中”- 对象仅存在于 db1 中; 状态“仅在目标中”- 对象仅存在于 db2 中; 状态 'In both schemas' - 对象存在于 db1 和 db2 中,但细节可能不同;例如: value 'varchar(255)/int(11)' 表示源字段类型为 'varchar(255)',目标为 'int(11)',value 'null' 表示细节相等;

SET @source_db = 'db1';
SET @target_db = 'db2';

SELECT 
  'Only in source' exist_type,
  c1.table_schema, c1.table_name, c1.column_name, c1.ordinal_position, c1.column_default, c1.is_nullable, c1.numeric_precision, c1.numeric_scale, c1.character_set_name, c1.collation_name, c1.column_type, c1.column_key, c1.extra, c1.column_comment
FROM
  (SELECT * FROM information_schema.columns WHERE TABLE_SCHEMA = @source_db) c1
  LEFT JOIN (SELECT * FROM information_schema.columns WHERE TABLE_SCHEMA = @target_db) c2
    ON c1.TABLE_name = c2.TABLE_name AND c1.column_name = c2.column_name
WHERE c2.column_name is null

UNION ALL

SELECT
  'Only in target' exist_type,
  c2.table_schema, c2.table_name, c2.column_name, c2.ordinal_position, c2.column_default, c2.is_nullable, c2.numeric_precision, c2.numeric_scale, c2.character_set_name, c2.collation_name, c2.column_type, c2.column_key, c2.extra, c2.column_comment
FROM
  (SELECT * FROM information_schema.columns WHERE TABLE_SCHEMA = @source_db) c1
  RIGHT JOIN (SELECT * FROM information_schema.columns WHERE TABLE_SCHEMA = @target_db) c2
    ON c1.TABLE_name = c2.TABLE_name AND c1.column_name = c2.column_name
WHERE c1.column_name is null

UNION ALL

SELECT 
  'In both schemas' exist_type,
  CONCAT(c1.table_schema, '/', c2.table_schema),
  c1.table_name, c1.column_name,
  IF(c1.ordinal_position = c2.ordinal_position OR c1.ordinal_position IS NULL AND c2.ordinal_position IS NULL, NULL, CONCAT_WS('/', IFNULL(c1.ordinal_position, ''), IFNULL(c2.ordinal_position, ''))),
  IF(c1.column_default = c2.column_default OR c1.column_default IS NULL AND c2.column_default IS NULL, NULL, CONCAT_WS('/', IFNULL(c1.column_default, ''), IFNULL(c2.column_default, ''))),
  IF(c1.is_nullable = c2.is_nullable OR c1.is_nullable IS NULL AND c2.is_nullable IS NULL, NULL, CONCAT_WS('/', IFNULL(c1.is_nullable, ''), IFNULL(c2.is_nullable, ''))),
  IF(c1.numeric_precision = c2.numeric_precision OR c1.numeric_precision IS NULL AND c2.numeric_precision IS NULL, NULL, CONCAT_WS('/', IFNULL(c1.numeric_precision, ''), IFNULL(c2.numeric_precision, ''))),
  IF(c1.numeric_scale = c2.numeric_scale OR c1.numeric_scale IS NULL AND c2.numeric_scale IS NULL, NULL, CONCAT_WS('/', IFNULL(c1.numeric_scale, ''), IFNULL(c2.numeric_scale, ''))),
  IF(c1.character_set_name = c2.character_set_name OR c1.character_set_name IS NULL AND c2.character_set_name IS NULL, NULL, CONCAT_WS('/', IFNULL(c1.character_set_name, ''), IFNULL(c2.character_set_name, ''))),
  IF(c1.collation_name = c2.collation_name OR c1.collation_name IS NULL AND c2.collation_name IS NULL, NULL, CONCAT_WS('/', IFNULL(c1.collation_name, ''), IFNULL(c2.collation_name, ''))),
  IF(c1.column_type = c2.column_type OR c1.column_type IS NULL AND c2.column_type IS NULL, NULL, CONCAT_WS('/', IFNULL(c1.column_type, ''), IFNULL(c2.column_type, ''))),
  IF(c1.column_key = c2.column_key OR c1.column_key IS NULL AND c2.column_key IS NULL, NULL, CONCAT_WS('/', IFNULL(c1.column_key, ''), IFNULL(c2.column_key, ''))),
  IF(c1.extra = c2.extra OR c1.extra IS NULL AND c2.extra IS NULL, NULL, CONCAT_WS('/', IFNULL(c1.extra, ''), IFNULL(c2.extra, ''))),
  IF(c1.column_comment = c2.column_comment OR c1.column_comment IS NULL AND c2.column_comment IS NULL, NULL, CONCAT_WS('/', IFNULL(c1.column_comment, ''), IFNULL(c2.column_comment, '')))
FROM
  (SELECT * FROM information_schema.columns WHERE TABLE_SCHEMA = @source_db) c1
  JOIN (SELECT * FROM information_schema.columns WHERE TABLE_SCHEMA = @target_db) c2
    ON c1.TABLE_name = c2.TABLE_name AND c1.column_name = c2.column_name;

可以修改此脚本以查找触发器和例程之间的差异。

【讨论】:

  • 哇,这就是我要说的。
【解决方案2】:

您需要的所有数据都应该在 information_schema 数据库的表中。

您也许可以使用某种仅向您显示差异的联接进行比较,但尝试在查询或单个查询中进行比较似乎是解决问题的一种过于复杂的方法,我认为您是朝自己的脚开枪。

快速简便的解决方案是将每个数据库的 mysqldump --no-data 的内容转换为 diff,或者从信息架构中提取数据并进行比较。

【讨论】:

  • 我只是想知道表和存储过程之间是否有变化,这样我就不必因为可能不同步的东西而失眠。
【解决方案3】:

t1 与 t2 比较

select 
 (case t1.table_name=t2.table_name when 1 then concat(t1.table_name,"==",t2.table_name) else concat(t1.table_name,"!=",t2.table_name) end) as table_name,
 (case t1.column_name=t2.column_name when 1 then concat(t1.column_name,"==", t2.column_name) else concat(t1.column_name,"!=", t2.column_name) end) as column_name,
 (case t1.ORDINAL_POSITION=t2.ORDINAL_POSITION when 1 then concat(t1.ORDINAL_POSITION,"==", t2.ORDINAL_POSITION) else concat(t1.ORDINAL_POSITION,"!=", t2.ORDINAL_POSITION) end) as ORDINAL_POSITION
......--columns in information_schema
from columns t1 left join (select * from columns where table_schema='t2') t2 on t2.table_name=t1.table_name and t2.column_name=t1.column_name where t1.table_schema='t1'; 

希望有帮助!!

【讨论】:

    【解决方案4】:

    Johan,您已经通过说您想要一个“查询”来比较数据库来缩小您的回答范围:)

    不过,我对您的建议是考虑“二进制日志”。我已经成功地将它用于类似的目的。

           a) enable logs 
           b) Go through all binary logs files 
           c) grep desired statements
           d) at then end purge/reset binary logs  ie. RESET MASTER 
    

    显然,您将在生产数据库上执行此操作。

    其他方式可能是:How to synchronize development and production database

    【讨论】:

      【解决方案5】:

      这是一个古老的,但它的工作原理。基于 devart 的示例,我继续构建过程和函数的比较:

      SET @source_db = 'qls_projects_for_comparison';
      SET @target_db = 'qls_projects';
      
      -- Pick one and comment out the other
      -- SET @routine_type = 'FUNCTION';
      SET @routine_type = 'PROCEDURE';
      
      -- Get the ones only in the source
      SELECT
        'Only in SOURCE' exist_type, C1.ROUTINE_NAME, C1.ROUTINE_SCHEMA,         
      C1.ROUTINE_TYPE, C1.LAST_ALTERED, C1.DEFINER as 'Source Definer', C2.DEFINER 
      as     'Target Definer', def_compare as 'Compare Definitions'  
      FROM (    
      (SELECT *,'' as def_compare FROM INFORMATION_SCHEMA.ROUTINES WHERE 
      ROUTINE_TYPE = @routine_type AND ROUTINE_SCHEMA = @source_db) C1
      LEFT JOIN (SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_TYPE = 
      @routine_type AND ROUTINE_SCHEMA = @target_db) C2
      ON C1.ROUTINE_NAME = C2.ROUTINE_NAME
      )
      WHERE C2.ROUTINE_NAME IS NULL
      
      UNION ALL
      
      -- Get the ones only in the target
      SELECT
        'Only in TARGET' exist_type, C2.ROUTINE_NAME, C2.ROUTINE_SCHEMA,             
      C2.ROUTINE_TYPE, C2.LAST_ALTERED, C1.DEFINER as 'Source Definer', C2.DEFINER 
      as 'Target Definer', def_compare as 'Compare Definitions'  
      FROM (    
      (SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_TYPE = 
      @routine_type AND ROUTINE_SCHEMA = @source_db) C1
      RIGHT JOIN (SELECT *,'' as def_compare FROM INFORMATION_SCHEMA.ROUTINES 
      WHERE ROUTINE_TYPE = @routine_type AND ROUTINE_SCHEMA = @target_db) C2
      ON C1.ROUTINE_NAME = C2.ROUTINE_NAME
      )
      WHERE C1.ROUTINE_NAME IS NULL
      
      UNION ALL
      
      -- Get the ones in both and compare the bodies of the routines 
      
      SELECT 
      'In both schemas' exist_type
      , C2.ROUTINE_NAME
      , C2.ROUTINE_SCHEMA
      , C2.ROUTINE_TYPE
      , C2.LAST_ALTERED
      , C1.DEFINER as 'Source Definer'
      , C2.DEFINER as 'Target Definer', 
      IF(C1.ROUTINE_DEFINITION=C2.ROUTINE_DEFINITION, 'Matches','Does Not Match') 
      as 'Compare Definitions'
      FROM (    
         (SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_TYPE = 
      @routine_type AND ROUTINE_SCHEMA = @source_db) C1
        INNER JOIN (SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_TYPE = 
      @routine_type AND ROUTINE_SCHEMA = @target_db) C2
          ON C1.ROUTINE_NAME = C2.ROUTINE_NAME
      )
      

      【讨论】:

        猜你喜欢
        • 2020-02-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-13
        • 1970-01-01
        • 1970-01-01
        • 2020-02-04
        • 1970-01-01
        相关资源
        最近更新 更多