项目场景:

在进行慢sql评审时,发现测试环境增加了索引生产并没有。然后有些表字段长度也不一样,坑大发了。决定写一个小工具对比一下测试跟生产表结构差异,大致思路连接数据库获取建表语句进行对比,忽略主键自增id。因为测试跟生产主键id自增会有不同,如果建表语句不一致,则需要比对文本高亮显示。在网上copy了一个别人写的高亮算法,生成了一个html预览。直接上代码


package com.xuyw.test.export;import com.alibaba.druid.pool.DruidDataSource;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.io.FileUtils;
import org.springframework.jdbc.core.JdbcTemplate;import java.io.File;
import java.io.IOException;
import java.util.*;/*** @author one.xu* @version v1.0* @description* @date 2022/1/5 17:59*/
public class DbComparedTest {private static JdbcTemplate db1;private static JdbcTemplate db2;static {db1 = new JdbcTemplate();DruidDataSource dataSource = new DruidDataSource();dataSource.setUrl("");dataSource.setUsername("");dataSource.setPassword("");db1.setDataSource(dataSource);db2 = new JdbcTemplate();DruidDataSource dataSource2 = new DruidDataSource();dataSource2.setUrl("");dataSource2.setUsername("");dataSource2.setPassword("");db2.setDataSource(dataSource2);}//移除AUTO_INCREMENTprivate static String handTable(String table) {return table.replaceAll("AUTO_INCREMENT=\\d+", "").trim();}//文本对比,高亮显示public static String getcompareStr(String char1, String char2) {String bcolor = "<span style='background-color:yellow;color:red;'>";String ecolor = "</span>";StringBuffer sb = new StringBuffer();char[] a = new char[char1.length()];for (int i = 0; i < char1.length(); i++) {a[i] = char1.charAt(i);}char[] b = new char[char2.length()];for (int i = 0; i < char2.length(); i++) {b[i] = char2.charAt(i);}// 不同字符集合Map<Object, Object> map1 = new HashMap<>();// 包含字符集合Map<Object, Object> map2 = new HashMap<>();for (int i = 0; i < a.length; i++) {if (i == a.length - 1) {if (i > 1) {if (String.valueOf(b).contains(String.valueOf(a[i - 1]) + String.valueOf(a[i]))) {map2.put(i - 1, a[i - 1]);map2.put(i, a[i]);} else {map1.put(i, a[i]);}} else {map2.put(i, a[i]);}} else {if (String.valueOf(b).contains(String.valueOf(a[i]) + String.valueOf(a[i + 1]))) {if (i > 1) {if (String.valueOf(b).contains(String.valueOf(a[i - 1]) + String.valueOf(a[i]))) {map2.put(i - 1, a[i - 1]);map2.put(i, a[i]);}} else {map2.put(i, a[i]);}} else {if (i > 0) {if (String.valueOf(b).contains(String.valueOf(a[i - 1]) + String.valueOf(a[i]))) {map2.put(i - 1, a[i - 1]);map2.put(i, a[i]);} else {map1.put(i, a[i]);}} else {map1.put(i, a[i]);}}}}for (int i = 0; i < a.length; i++) {if (map1.get(i) != null) {sb.append(bcolor).append(map1.get(i)).append(ecolor);} else if (map2.get(i) != null) {sb.append(map2.get(i));}}return sb.toString();}public static void main(String[] args) throws IOException {//需要比对的数据库名,多个逗号连接String dbs = "testDb1,testDb1";String tableSql = "select table_name,table_comment FROM information_schema.tables WHERE table_schema=?";//忽略比对的表名,多个逗号连接  支持正则String ignoreTable = "|(msg_log_\\w+)|(hand_log_\\w+)";String tableCreateSql = "show create table ";List<Map<String, Object>> tableDiffList = new ArrayList<>();Map<String, Object> diffMap;Map<String, Integer> dbTableCountMap = new HashMap<>();int dbTableCount = 0;for (String db : dbs.split(",")) {dbTableCount = 0;List<Map<String, Object>> tables = db1.queryForList(tableSql, db);for (int j = 0; j < tables.size(); j++) {String table = tables.get(j).get("table_name").toString();if (table.matches(ignoreTable)) {continue;}diffMap = new HashMap<>();Map<String, Object> sourceTableMap = db1.queryForMap(tableCreateSql + db + "." + table);String sourceTable = handTable(MapUtils.getString(sourceTableMap, "Create Table"));diffMap.put("dbName", db);diffMap.put("sourceTable", sourceTable);Map<String, Object> targetTableMap;try {targetTableMap = db2.queryForMap(tableCreateSql + db + "." + table);} catch (Exception e) {dbTableCount = dbTableCount + 1;diffMap.put("targetTable", "不存在");tableDiffList.add(diffMap);continue;}String targetTable = handTable(MapUtils.getString(targetTableMap, "Create Table"));if (sourceTable.equals(targetTable)) {continue;}diffMap.put("targetTable", getcompareStr(targetTable, sourceTable));diffMap.put("sourceTable", getcompareStr(sourceTable, targetTable));tableDiffList.add(diffMap);dbTableCount = dbTableCount + 1;}dbTableCountMap.put(db, dbTableCount);}StringJoiner html = new StringJoiner("\n");html.add("<table style=\"font-size:12px;color:#333333;width:100%;border-width: 1px;border-color: #729ea5;border-collapse: collapse;\" border=\"1\">\n" +"<tr><th >数据库名</th><th>源表</th><th>对比表</th></tr>");for (Map<String, Object> m : tableDiffList) {String dbName=m.get("dbName").toString();Integer dbTabeCount=dbTableCountMap.get(dbName);if(dbTabeCount!=null){html.add("<tr> <td rowspan=\""+dbTabeCount+"\">"+dbName+"</td>");dbTableCountMap.remove(dbName);}html.add("<td>\n" +"<pre> "+m.get("sourceTable").toString()+" <pre>\n" +"</td>");html.add("<td>\n" +"<pre> "+m.get("targetTable").toString()+" <pre>\n" +"</td>");html.add("</tr>");}html.add("</table>");FileUtils.writeStringToFile(new File("d:\\DbComparedTest.html"), html.toString());}
}

对比效果如下


mysql 表结构差异对比小工具相关推荐

  1. mysql schema 同步_GitHub - naryn/mysql-schema-sync: mysql表结构自动同步工具

    mysql-schema-sync mysql表结构自动同步工具 用于将 线上 数据库结构变化同步到 本地环境! 支持功能: 同步新表 同步字段 变动:新增.修改 同步索引 变动:新增.修改 支持预览 ...

  2. 效率爆表的创作小工具

    效率爆表的创作工具 文章目录 效率爆表的创作工具 零.序 一.截图神器 Snipaste 1.1. 快速截屏 1.2.快速钉屏 1.3.钉屏切换 1.4.窗口自动识别 1.5.延时截屏 二.图片上传神 ...

  3. MySql 表操作指令小全与案例 2

    MySql 表增删查改小全 2 增删查改--进阶 键值约束与扩展属性 分组查询 ER关系图+三大范式 ER关系图 三大范式 多表联查 内连接 外连接 子查询 合并查询 注:本篇博客为 MySql 表操 ...

  4. mysql数据库表结构对比_mysqldiff工具对比mysql数据库表结构差异

    主要介绍使用mysqldiff工具来对比表结构的差异,其实在5.6版本之后通过查询information库中的系统表也能对比出来,但是mysqldiff还有一个好处就是可以直接生产差异的SQL语句这个 ...

  5. MySQL表数据对比

    最近遇到一个头疼的问题,就是表字段的对比,在本地数据库中给一些表进行一些字段的修改,没有做记录,服务器上的要同步,这样就很头疼了,找了几个可视化的工具,navicat 经常卡死,SQLyog - 32 ...

  6. 卸载mysql数据库,利用小工具超级简单!!!

    1.去网盘下载工具(内存很小!!) 链接:https://pan.baidu.com/s/1oYFf7r14U1H6Sgx9LVPsBA?pwd=hszs 提取码:hszs 2.进入工具 3.然后根据 ...

  7. 在线的MySQL数据库表结构对比工具

    在项目部署上线前,测试版和正式版的数据库表结构做过哪些变更,如果没有做好实时记录,那么就需要对比找出差异,否则代码部分更新后,可能导致功能异常. 数据库表结构对比的工具很多,但是为了方便部署同步的,这 ...

  8. 对比MySQL表数据内容方式汇总

    一. mysql自带的checksum命令: 可在不同服务器通过checksum值对比两张表是否一致, 加上EXTENDED参数表示逐行扫描, 结果更为可靠; 执行过程会给表加上System lock ...

  9. mysql model first,一个支持 CodeFirst/DbFirst/ModelFirst 的数据库小工具

    一个支持 CodeFirst/DbFirst/ModelFirst 的数据库小工具 Intro DbTool 是一个支持 CodeFirst/DbFirst/ModelFirst 的数据库小工具,原本 ...

最新文章

  1. pytorch CrossEntropyLoss测试
  2. win10计算机记录,启用Windows 10计算器中的历史记录功能 | MOS86
  3. 1262. 可被三整除的最大和(贪心||动态规划)
  4. 基于zbus的MySQL透明代理(100行)
  5. [jQuery] jquery.extend与jquery.fn.extend的区别?
  6. hive不在同一台机 hue_环境篇:呕心沥血@CDH线上调优
  7. 外媒:全球芯片短缺已影响洗衣机和烤面包机等小家电生产
  8. 【连载】【FPGA黑金开发板】NIOS II那些事儿--LED实验(四)
  9. CSS基础选择器之标签选择器(CSS、HTML)
  10. SONIC架构简要分析-数据库
  11. 二分图匹配问题之km算法代码
  12. 校验手机号正则,支持166及199等手机号
  13. 用edge调试安卓或者手机app的样式
  14. python 2 入门
  15. 河南理工大学 计算机 研究生就业,河南理工大学好就业吗?附河南理工大学就业率最高的专业名单...
  16. 洛谷P2448 无尽的生命 树状数组
  17. Java基础教程--安卓入门教程(七)
  18. uestc_retarded 模板
  19. cmd中运行exe的简单命令
  20. TypeError: sequence item 0: expected string, int found

热门文章

  1. 计算机二级swot分析,基于SWOT模型的学科竞争力研究
  2. isis宣告网络_isis简要原理、实验和常用命令
  3. 看看人家用三天写出来的完整项目,直接惊艳了面试官!
  4. poj2421修建道路
  5. com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Access denied for user 'chong'@'localhost
  6. Seaborn多图组合
  7. openwrt 环境搭建(win10子系统)
  8. Java 继承 与 抽象类
  9. 传奇开服一条龙GEE引擎登录器配置教程
  10. 【方案分享】自助彩票终端布局商场,彩票行业智能营销新模式