Mysql建表脚本转ClinkHouse建表脚本

Posted 我永远信仰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql建表脚本转ClinkHouse建表脚本相关的知识,希望对你有一定的参考价值。

mysql建表脚本转CK

前置知识

主要是类型的转换、和空、非空的问题

整形

  • ClickHouse则直接使用Int8、Int16、Int32和Int64指代4种大小的Int类型,其末尾的数字正好表明了占用字节的大小(8位=1字节)

  • mysql中: int(M)的作用于int的范围明显是无关的,int(M)只是用来显示数据的宽度,我们能看到的宽度。当字段被设计为int类型,那么它的范围就已经被写死了(-2147483648~2147483647),与M无关。



CK的NOT NULL、NULL和Nullable的区别

  1. 如果字段声明为 not null它的默认值已由它的类型而定,不允许再为其设置默认值,比如int为0,String为空串。不需要显式声明
  2. 如果字段显式声明为null,默认值为NULL。
  3. 如果字段声明为Nullable,默认为NULL,可设置默认值,损耗性能。
/**
 * @Author yhchen
 * @Date 2022/3/8 10:22
 */
public class MysqlToCK2 
    public static void main(String[] args) 
    //将sql复制到这里
        String createTable = "DROP TABLE IF EXISTS `runoob_tbl`;\\n" +
                "CREATE TABLE IF NOT EXISTS `runoob_tbl`(\\n" +
                "   `runoob_id` int UNSIGNED AUTO_INCREMENT,\\n" +
                "   `runoob_title` VARCHAR(100) NOT NULL,\\n" +
                "   `runoob_author` VARCHAR(40) NOT NULL,\\n" +
                "   `submission_date` DATE,\\n" +
                "   PRIMARY KEY ( `runoob_id` )\\n" +
                ")ENGINE=InnoDB DEFAULT CHARSET=utf8;";
        String res = changeMysqlTableToClickHouse(createTable);
        System.out.println("转换后的建表语句为:");
        System.out.println(res);
        System.out.println("需要删除ENGINE的上一行最后的一个逗号");
    

    public static String changeMysqlTableToClickHouse(String tableName) 
        String tables = tableName;
        String primaryKey = "`id`";//默认id
        String[] rows = tables.split("\\n");
        StringBuilder replaceTables = new StringBuilder();
        Boolean haveKey = false;
        int i = 0;
        for (String row : rows) 
            // 注释,不处理
            if (row.contains("--")) 
                replaceTables.append(row + "\\n");
                continue;
            
            if (row.contains("KEY")) 
                if (row.contains("PRIMARY")) 
                    haveKey = true;
                    primaryKey = row.substring(row.indexOf("(") + 1, row.indexOf(")"));
                
                // 跳过、不添加
                continue;
            
            if (row.contains("ENGINE=InnoDB")) 
                // 引擎替换
                row = ") ENGINE = ReplacingMergeTree";
            

            // 无关删除
            String changeRow = row.replaceAll("AUTO_INCREMENT", "")
                    .replaceAll("CHARACTER SET utf8mb4", "")
                    .replaceAll("CHARACTER SET utf8", "")
                    .replaceAll("ON UPDATE CURRENT_TIMESTAMP", "")
                    .replaceAll("CURRENT_TIMESTAMP", "")
                    .replaceAll("( DEFAULT CHARSET).*", "")
                    // 时间替换
                    .replaceAll("datetime DEFAULT NULL", " DateTime ")
                    .replaceAll(" datetime ", " DateTime ");

            /*String规则*/
            // 为空,字符串
            changeRow = changeRow.replaceAll("(` ).*(char).*(DEFAULT NULL)", "` String NULL");
            changeRow = changeRow.replaceAll("(` ).*(char).*(DEFAULT '')", "` String");
            // changeRow = changeRow.replaceAll("(DEFAULT '')", "NULL");
            // 非空,字符串
            changeRow = changeRow.replaceAll("(` ).*(char).*(NOT NULL)", "` String");
            changeRow = changeRow.replaceAll("text", "String");
            changeRow = changeRow.replaceAll("(DEFAULT NULL)", "NULL");
            changeRow = changeRow.replaceAll("(NOT NULL)", "");

            // 以空格分割
            String[] changeColumns = changeRow.split("[ ]");
            //      System.out.println(changeRow);
            // 含有int的替换规则
            if (changeColumns[3].contains("int") || changeColumns[3].contains("bigint")
                    ||changeColumns[3].contains("INT")) 
                changeColumns[3].replaceAll("INT","int");
                changeColumns[3].replaceAll("BIGINT","bigint");
                // 将括号内的数字拿出来
                int length = Integer.parseInt(changeColumns[3]
                        .replaceAll("bigint", "")
                        .replaceAll("tinyint", "")
                        .replaceAll("int", "")
                        .replaceAll("\\\\(", "")
                        .replaceAll("\\\\)", ""));
                // 获取数据类型
                String type = changeColumns[3].substring(0, changeColumns[3].indexOf("("));
                // 处理int 是否可以为空值
                String last = " NULL";
                String[] _int = "Int8", "Int16", "Int32", "Int64";
                if (changeRow.contains("DEFAULT NULL")) 
                    changeRow = changeRow.replaceAll("DEFAULT NULL", "");
                    for (int j = 0; j < _int.length; j++) 
                        _int[j] = _int[j] + last;
                    
                
                if ("tinyint".equals(type)) 
                    changeRow = changeRow
                            .replaceFirst(type + "\\\\(" + length + "\\\\)", _int[0]);
                 else if ("smallint".equals(type)) 
                    changeRow = changeRow
                            .replaceFirst(type + "\\\\(" + length + "\\\\)", _int[1]);
                 else if ("int".equals(type) || "mediumint".equals(type)) 
                    changeRow = changeRow
                            .replaceFirst(type + "\\\\(" + length + "\\\\)", _int[2]);
                 else 
                    changeRow = changeRow
                            .replaceFirst(type + "\\\\(" + length + "\\\\)", _int[3]);
                
            

            replaceTables.append(changeRow.trim() + "\\n");
            if (i == 0) 
                replaceTables.append("\\n");
            
            i++;
        
        if (replaceTables.toString().contains(",) ENGINE = Memory")) 
            String temp = replaceTables.substring(0, replaceTables.indexOf(",) ENGINE = Memory"));
            replaceTables = new StringBuilder(temp + ") ENGINE = Memory ");
        
        replaceTables.toString().replaceAll("CREATE TABLE `" + tableName + "`", tableName + "_local");
        if (haveKey) 
            replaceTables.append("PRIMARY KEY " + primaryKey);
        
        replaceTables.append("\\nORDER BY " + primaryKey);
        replaceTables.append(";");
        return replaceTables.toString();
    

以上是关于Mysql建表脚本转ClinkHouse建表脚本的主要内容,如果未能解决你的问题,请参考以下文章

Mysql建表脚本转ClickHouse建表脚本

mysql初始化数据库建表脚本

获取MySQL中某个数据库下所有表建表语句的DDL

接近50道经典SQL练习题,附建表SQL解题SQL

MySQL批量数据脚本示例

三种常用的MySQL建表语句(转)