Mysql根据一个基库生成其他库与其不同的库升级脚本

今天研究了一下不同数据库之间如何做同步。弄了一个升级工具类,希望以后还能有所帮助。

public class UpgradeDataBase {

    public static void main(String[] args) {
        //两个不同数据库名称
        List<String> sqls = UpgradeDataBaseToStandardDataBase("database1", "database2");
        for(String sql : sqls) {
            System.out.println(sql);
        }
    }

    /**
     * 将基准库里有的表字段,以名称为基准,生成同步到目标库中的脚本
     */
    public static List<String> UpgradeDataBaseToStandardDataBase(String standard, String target) {

        List<String> upgradeSqls = new ArrayList<>();

        List<String> standardTables = new ArrayList<>();
        List<String> targetTables = new ArrayList<>();

        Connection connStandard = null;
        Connection connTarget = null;

        Statement stmtStandard = null;
        Statement stmtTarget = null;

        ResultSet rsStandard = null;
        ResultSet rsTarget = null;

        try {
            Properties props = Resources.getResourceAsProperties("jdbc.properties");
            String url = props.getProperty("url");
            String driver = props.getProperty("driver");
            String username = props.getProperty("username");
            String password = props.getProperty("password");

            Class.forName(driver).newInstance();
            //拿到2个库的链接
            connStandard = DriverManager.getConnection(url, username, password);
            connStandard.setCatalog(standard);

            connTarget = DriverManager.getConnection(url, username, password);
            connTarget.setCatalog(target);

            stmtStandard = connStandard.createStatement();
            stmtTarget = connTarget.createStatement();

            //先把2个库所有的表查出来
            stmtStandard.execute("show tables");
            stmtTarget.execute("show tables");

            rsStandard = stmtStandard.getResultSet();
            rsTarget = stmtTarget.getResultSet();

            while (rsStandard.next()){
                standardTables.add(rsStandard.getString(1));
            }

            while (rsTarget.next()){
                targetTables.add(rsTarget.getString(1));
            }
            //循环基准库中每一张表
            for(String table : standardTables) {
                if("SM_USER".equals(table)) {
                    continue;
                }
                if(targetTables.contains(table)) {
                    Map<String, Map<String, String>> standardColumns = new HashMap<>();
                    Map<String, Map<String, String>> targetColumns = new HashMap<>();
                    //检查每一个字段,
                    //1.首先先查出目标库和基准库该表的所有字段
                    stmtStandard.execute("show columns from " + table + " from " + standard);
                    rsStandard = stmtStandard.getResultSet();
                    while (rsStandard.next()){

                        Map<String, String> map = new HashMap<>();
                        map.put("Field", rsStandard.getString("Field"));//列名
                        map.put("Type", rsStandard.getString("Type"));//类型+长度
                        map.put("Null", rsStandard.getString("Null"));//是否可为空
                        map.put("Key", rsStandard.getString("Key"));//是否主键
                        map.put("Default", rsStandard.getString("Default"));//默认值
                        map.put("Extra", rsStandard.getString("Extra"));//其他(自增列,触发器等)
                        standardColumns.put(rsStandard.getString("Field"), map);
                    }

                    stmtTarget.execute("show columns from " + table + " from " + target);
                    rsTarget = stmtTarget.getResultSet();
                    while (rsTarget.next()){

                        Map<String, String> map = new HashMap<>();
                        map.put("Field", rsTarget.getString("Field"));//列名
                        map.put("Type", rsTarget.getString("Type"));//类型+长度
                        map.put("Null", rsTarget.getString("Null"));//是否可为空
                        map.put("Key", rsTarget.getString("Key"));//是否主键
                        map.put("Default", rsTarget.getString("Default"));//默认值
                        map.put("Extra", rsTarget.getString("Extra"));//其他(自增列,触发器等)
                        targetColumns.put(rsTarget.getString("Field"), map);
                    }

                    //2.以基准库为准,逐个列比较
                    //TODO 没有处理Key(没有做主键、自增处理)
                    for(String column : standardColumns.keySet()) {
                        if(targetColumns.containsKey(column)) {//存在这一列
                            boolean needGeneSql = false;
                            StringBuffer buffer = new StringBuffer();
                            //类型有变化, 但是不管类型有没有变化,后续的语句都需要
//                            if(standardColumns.get(column).get("Type") != null && !standardColumns.get(column).get("Type").equals(targetColumns.get(column).get("Type"))) {
//                                buffer.append(standardColumns.get(column).get("Type"));
//                            }
                            buffer.append(standardColumns.get(column).get("Type"));
                            //默认值有变
                            if(standardColumns.get(column).get("Default") != null && !standardColumns.get(column).get("Default").equals(targetColumns.get(column).get("Default"))) {
                                buffer.append(" default " + standardColumns.get(column).get("Default"));
                                needGeneSql = true;
                            }
                            //是否可空有变
                            if(standardColumns.get(column).get("Null") != null && !standardColumns.get(column).get("Null").equals(targetColumns.get(column).get("Null"))) {
                                buffer.append(("NO".equals(standardColumns.get(column).get("Null")) ? " not null " : " null "));
                                needGeneSql = true;
                            }
                            //处理自增长等
                            if(standardColumns.get(column).get("Extra") != null && !standardColumns.get(column).get("Extra").equals(targetColumns.get(column).get("Extra"))) {
                                buffer.append(" ").append(standardColumns.get(column).get("Extra"));
                                needGeneSql = true;
                            }
                            if(needGeneSql) {
                                String changeColumnSql = "alter table " + table + " change " + column + " " + column + " " + buffer.toString() + ";";
                                upgradeSqls.add(changeColumnSql);
                            }
                        }
                        else{
                            String addColumnSql = "alter table " + table +
                                    " add column " + column + " " +
                                    standardColumns.get(column).get("Type") + " default " + standardColumns.get(column).get("Default") +
                                    ("NO".equals(standardColumns.get(column).get("Null")) ? " not null " : " null ") + ";";
                            upgradeSqls.add(addColumnSql);
                        }
                    }
                }
                else{//目标库中,没有基准库的表
                    stmtStandard.execute("show create table " + table);
                    rsStandard = stmtStandard.getResultSet();
                    String createSql = null;
                    while (rsStandard.next()){
                        //第2列是建表语句
                        createSql = rsStandard.getString(2);
                        upgradeSqls.add(createSql + ";");
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                rsStandard.close();
                rsTarget.close();
                stmtStandard.close();
                stmtTarget.close();
                connStandard.close();
                connTarget.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
        return upgradeSqls;

    }
}

  

  

时间: 2024-11-11 23:57:42

Mysql根据一个基库生成其他库与其不同的库升级脚本的相关文章

Linux静态库生成指南

Linux静态库生成指南 Linux上的静态库,其实是目标文件的归档文件.在Linux上创建静态库的步骤如下: 写源文件,通过 gcc -c xxx.c 生成目标文件. 用 ar 归档目标文件,生成静态库. 配合静态库,写一个使用静态库中函数的头文件. 使用静态库时,在源码中包含对应的头文件,链接时记得链接自己的库. 下面通过实例具体讲解. 写源文件,生成目标文件. 第一个源文件 my_print.c #include <stdio.h> void cout(const char * mess

Linux下动态库生成和使用

Linux下动态库生成和使用 一.动态库的基本概念 1.动态链接库是程序运行时加载的库,当动态链接库正确安装后,所有的程序都可以使用动态库来运行程序.动态链接库是目标文件的集合,目标文件在动态链接库中的组织方式是按照特殊方式形成的.库中函数和变量的地址是相对地址,不是绝对地址,其真实地址在调用动态库的程序加载时形成. 2.动态链接库的名称有别名(soname), 真名(realname)和链接名(linker name).别名由一个前缀lib,然后是库的名字,再加上一个后缀“.so”构成.真名是

Linux下静态库生成和使用

Linux下静态库生成和使用 一.静态库概念 1.库是预编译的目标文件(object  files)的集合,它们可以被链接进程序.静态库以后缀为”.a”的特殊的存档(archive file)存储. 2.标准系统库可在目录/usr/lib与/lib中找到.比如,在类Unix系统中C语言的数序库一般存储为文件/usr/lib/libm.a.该库中函数的原型声明在头文件/usr/include/math.h中. 3.C标准库本身存储为/usr/lib/libc.a,它包含ANS1/ISO标准指定的函

一个可以自动生成静态库,自动安装程序的Makefile

.PHONY:clean install CC=g++ CFLAGS=-Wall -g BIN=libecho.a INCLUDE=echo SRC=src OBJS=Socket.o Rio.o TcpConnection.o PollPoller.o InetAddress.o TcpServer.o Thread.o Condition.o ThreadPool.o Exception.o Timer.o TimerThread.o STARD=-std=c++0x -rdynamic $

c# 使用ZXing.dll库生成二维码

最近工作中有需要一个需求,就是把一个服务地址生成二维码,可以用来扫码分享,网上找了下方法也比较多,我这里po一下调用ZXing.dll库生成二维码的方法吧.先简单介绍一下 ZXing库,ZXing库是一个开源Java类库,可用于生成和解析多种格式的1D/2D条形码:zxing遵循Apache License 2.0,只是工具而已,是不收费哒. ZXing库的下载地址:http://zxingnet.codeplex.com/ 点击下载,下载后解压压缩包: 把Zxing加到工程应用中,以下为核心代

PHP 使用GD库生成验证码 在图像上绘制汉字

PHP 并不仅限于创建 HTML 输出, 它也可以创建和处理包括 GIF, PNG, JPEG, WBMP 以及 XPM 在内的多种格式的图像. 更加方便的是,PHP 可以直接将图像数据流输出到浏览器. 要想在 PHP 中使用图像处理功能,你需要连带 GD 库一起来编译 PHP. GD 库和 PHP 可能需要其他的库, 这取决于你要处理的图像格式. 你可以使用 PHP 中的图像函数来获取下列格式图像的大小: JPEG, GIF, PNG, SWF, TIFF 和 JPEG2000.如果联合 ex

更新小红伞antivirus失败:生成更新结构失败。更新库生成错误 556

http://blog.csdn.net/pipisorry/article/details/45721521 更新小红伞antivirus失败 生成更新结构失败.更新库生成错误 556 15:14:34 [UPDLIB] [ERROR]   文件 C:\ProgramData\Avira\AntiVir Desktop\TEMP\UPDATE\antivirus\15.0.9.504\win\zh-cn\libeay32.dll.gz 的 MD5 与 info 文件中指定的 MD5 不同 15

一个让业务开发效率提高10倍的golang库

一个让业务开发效率提高10倍的golang库 此文除了是标题党,没有什么其他问题. 这篇文章推荐一个库,https://github.com/jianfengye/collection. 这个库是我在开发业务过程中 Slice 的频繁导致业务开发效率低,就产生了要做一个 Collection 包的想法.本文说说我开发这个库的前因后果 Golang 适不适合写业务? 最近一个逻辑非常复杂的业务,我用 Golang 来开发.开发过程不断在问一个问题,Golang 适不适合写业务? 业务说到底,是一大

mysql(五)------针对主从同步的情况两个库进行数据校对及恢复

两台MySQL,发生了种种种种,导致了两个表的数据不一致,但是同步还在正常进行,后来意识到这种问题(可能之前skip啊,或者一开始搭建的时候就是不一致的状态),该如何修复呢?如果数据量小的情况可以考虑从新导数据,如果数据量很大的话,那就太要命了于是可以用percona-toolkit这个工具修复并并检查这种情况的再主备同步的时候在进行如下操作:在主库上安装pt-table-checksum安装: 1.安装软件包: # yum install perl perl-devel perl-Time-H