使用java代码导出数据库sql文件

使用java代码导出数据库sql文件

导出目标

导出包含数据库表结构、索引、外键以及表里面的数据

导出分析
1. 我们不需要导出所有的表 比如 _copy、_bak之类的备份表。
2. 我们不需要导出日志表(如 _log表)中的数据 只需要表结构
3. 基于SaaS架构的数据库一般会有一个租户id,比如项目id、租户id之类的,假设我们有需求,只想导出某个项目下的数据

导出工具类

 private static final Logger logger = LoggerFactory.getLogger(MySQLDatabaseTableStructureAndDataSQLExporter.class);

    /**
     * 数据库sql采集
     * @param ignoreTab 忽略采集哪些表
     * @param logTab 哪些表只采集表结构、不采集insert语句
     * @param projectIds 导出的项目id 多个逗号隔开【方法底层去判断数据库表是否有 project_id参数 如果有导出insert语句时就只导出指定项目下的数据】
     */
    private static void collectSql(List<String> ignoreTab, List<String> logTab, String projectIds) {
        String jdbcUrl = "jdbc:mysql://localhost:3306/数据库?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai";
        String username = "你的用户名";
        String password = "你的密码";
        String databaseName = "数据库"; // 修改为你要导出的数据库名

        String outputFilePath = databaseName+"output.sql"; // 修改为你想要输出的 SQL 文件路径

        long begin = System.currentTimeMillis();
        try (Connection connection = DriverManager.getConnection(jdbcUrl, username, password)) {
            DatabaseMetaData metaData = connection.getMetaData();
            ResultSet tableResultSet = metaData.getTables(databaseName, null, null, new String[]{"TABLE"});
            logger.info("数据库sql采集 开始 ");
            try (FileWriter fileWriter = new FileWriter(outputFilePath)) {
                fileWriter.write("SET FOREIGN_KEY_CHECKS = 0;" + "\n");	// 外键约束暂时不校验
                while (tableResultSet.next()) {
                    String tableName = tableResultSet.getString("TABLE_NAME");

                    if (hasRegex(tableName, ignoreTab)) {
                        // 表名含有 ignoreTab 中的字符,则忽略
                        continue;
                    }
                    long w1 = System.currentTimeMillis();
                    logger.info("数据库sql采集 tableName={} ", tableName);

                    boolean isLoginTab = hasRegex(tableName, logTab);    // 日志表里面的内容不同步

                    fileWriter.write("-- Table: " + tableName + "\n");

                    // 获取建表语句
                    StringBuilder createTableQuery = new StringBuilder();
                    Statement statement = connection.createStatement();
                    ResultSet resultSet = statement.executeQuery("SHOW CREATE TABLE " + tableName);
                    resultSet.next();
                    createTableQuery.append(resultSet.getString("Create Table")).append(";");
                    createTableQuery.append(System.lineSeparator());
                    fileWriter.write(createTableQuery.toString());

                    if (isLoginTab){
                        logger.info("数据库sql采集 tableName={}&耗时={}ms", tableName, (System.currentTimeMillis()-w1));
                        continue;
                    }


                    // 获取是否存在 "project_id" 字段
                    boolean hasProjectIdColumn = checkProjectIdColumn(connection, tableName);

                    String selectQuery ;
                    ResultSet dataResultSet;
                    PreparedStatement preparedStatement = null;
                    if (hasProjectIdColumn) {
                        selectQuery = "SELECT * FROM " + tableName + " WHERE project_id in (?)";
                        preparedStatement = connection.prepareStatement(selectQuery);
                        preparedStatement.setString(1, projectIds+""); // 修改为实际的 project_id   有些默认配置是项目id为0的
                        dataResultSet = preparedStatement.executeQuery();
                    } else{
                        selectQuery = "SELECT * FROM " + tableName;
                        dataResultSet = statement.executeQuery(selectQuery);
                    }

                    while (dataResultSet.next()) {
                        ResultSetMetaData rsMetaData = dataResultSet.getMetaData();
                        int columnCount = rsMetaData.getColumnCount();

                        StringBuilder insertQuery = new StringBuilder("INSERT INTO " + tableName + " VALUES (");

                        for (int i = 1; i <= columnCount; i++) {
                            Object value = dataResultSet.getObject(i);
                            if (i > 1) {
                                insertQuery.append(", ");
                            }
                            if (value == null) {
                                insertQuery.append("null");
                            }else {
                                if (rsMetaData.getColumnTypeName(i).equalsIgnoreCase("JSON")) {
                                    // Handle JSON type data
                                    String jsonValue = escapeJsonSpecialCharacters(value.toString());
                                    insertQuery.append("'").append(jsonValue).append("'");
                                } else {
                                    if (value instanceof Boolean) {
                                        insertQuery.append("'").append((Boolean)value ? 1 : 0).append("'");
                                    }else {
                                        insertQuery.append("'").append(value).append("'");
                                    }

                                }

                            }
                        }

                        insertQuery.append(");\n");
                        fileWriter.write(insertQuery.toString());
                    }

                    dataResultSet.close();
                    statement.close();
                    if (preparedStatement != null) {
                        preparedStatement.close();
                    }
                    logger.info("数据库sql采集 tableName={}&耗时={}ms", tableName, (System.currentTimeMillis()-w1));

                }

                fileWriter.write("SET FOREIGN_KEY_CHECKS = 1;");

            } catch (IOException e) {
                e.printStackTrace();
            }

            tableResultSet.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        logger.info("数据库sql采集 结束 耗时={}ms ", (System.currentTimeMillis() - begin));
    }

    private static boolean hasRegex(String tableName, List<String> ignoreTab) {
        if (CollectionUtils.isEmpty(ignoreTab)) {
            return false;
        }

        for (String s : ignoreTab) {
            if (tableName.contains(s)){
                return true;
            }
        }

        return false;
    }

    private static String escapeJsonSpecialCharacters(String jsonValue) {
        return jsonValue
                .replace("\n", "\\n")
                .replace("\t", "\\t")
                .replace("\r", "\\r")
                .replace("\b", "\\b")
                .replace("\f", "\\f")
                .replace("\\", "\\\\")
                .replace("'", "\\'");
    }

    private static boolean checkProjectIdColumn(Connection connection, String tableName) throws SQLException {
        String query = "SHOW COLUMNS FROM " + tableName + " LIKE 'project_id'";
        try (PreparedStatement preparedStatement = connection.prepareStatement(query)) {
            ResultSet resultSet = preparedStatement.executeQuery();
            return resultSet.next();
        }
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、简介 1.1前言 1、由于最近工作一直用Oracle,故对Oracle数据库研究为对象。 2、根据工作业务需求实际情况进行功能研发。为什么要开发呢?因为在数据库升级或者迁移的时候,为了保证不同环境不同数据库数据保持同步,故数据库SQL脚本非常作用。比如:数据库主脚本,副脚本,增量脚本。 3、 什么是主脚本、副脚本、增量脚本呢? 3.1、主脚本指数据库表或存储过程,视图脚本,序列等脚本。 3.2、副脚本指必须执行主脚本之后才执行的脚本。换句话说在没执行主键脚本的情况下,副脚本执行之后会回滚事务失败。 3.3、增量脚本指在执行主脚本或副脚本之后,根据需求对某个表添加/修改约束(主外键约束,长度约束等),添加/修改字段/添加数据等情况对数据库结构改变处理的一种行为脚本。 1.2作用 1、 快速产出自定义规则需要的SQL脚本。 2、减少人工编写SQL脚本出错率问题,完全通过程序检测SQL准确性。 3、帮助开发人员提高SQL编写效率,减少人工编写SQL开发成本问题。 4、帮助开发人员节约时间,同时避免繁琐不必要编写SQL的工作。 二、实现方式与原理 2.1实现方式 1、实现方式分:正向与逆向实现。什么是正向与逆行呢【是否有鸡还是有蛋,先后道理同等】 2、正向方式:首先把设计好数据库表文档,把所有表的字段属性配置到EXCEL或者CSV格式的文件通过JXL/POI技术去读取文件的字段,再通过其他技术一系列程序处理之后生成所需要的SQL脚本。 3、逆向方式:首先有数据库表,然后通过ORM持久化技术连接数据库再读取表的字段等属性出来,再通过其他技术一系列程序处理之后生成所需要的SQL脚本。 2.2原理 对数据库软件内置核心表或视图查询出来存储用户行为表结构所有属性信息,对此属性结构信息进行分析与组装所需要SQL脚本。
目前,GitHub Copilot 是一个由 OpenAI 和 GitHub 合作开发的代码智能助手,它目前仅支持在 Visual Studio Code 编辑器中使用。而 Windows 11 是微软最新发布的操作系统,因此您可以按照以下步骤在 Windows 11 上安装 Copilot: 1. 安装 Visual Studio Code:访问 Visual Studio Code 官方网站(https://code.visualstudio.com/)下载最新版本的 Visual Studio Code 编辑器。根据您的操作系统选择合适的安装程序进行下载和安装。确保您选择适用于 Windows 11 的版本。 2. 打开 Visual Studio Code:安装完成后,打开 Visual Studio Code 编辑器。 3. 安装 Copilot 插件:在 Visual Studio Code 编辑器中,点击左侧的扩展图标(四个方块连接在一起的图标),搜索并找到 "GitHub Copilot" 插件。点击插件卡片右侧的 "Install" 按钮进行安装。 4. 登录 GitHub 账号:安装完成后,点击 Visual Studio Code 编辑器左下角的 GitHub Copilot 图标,然后点击 "Sign in with GitHub" 进行登录。确保您使用的是与 Copilot 关联的 GitHub 账号进行登录。 5. 使用 Copilot:安装和登录完成后,您可以在编写代码时享受 Copilot 提供的智能代码建议和补全功能。Copilot 可以根据上下文和您输入的代码,生成相关的代码片段和建议。 请注意,GitHub Copilot 目前仍然处于技术预览阶段,可能会有一些限制和使用上的问题。确保您已经阅读并理解了 Copilot 的使用条款和隐私政策。 希望这些步骤能帮助您在 Windows 11 上安装和使用 Copilot。如果您遇到任何问题,请及时与我联系。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值