MySQL与Oracle之间互相拷贝数据的Java程序

   2023-02-09 学习力0
核心提示:因为工作需要,先是需要将一个小型的MySQL数据库中的数据拷贝到Oracle中;近期又有需要将一个中型的Oracle数据库拷贝到MySQL中。曾经找过网上各种转换工具,大多收费的,自己写个吧,还一切可控。转换的前提是两种数据库中已经存在相同的数据结构,可以自己利

因为工作需要,先是需要将一个小型的MySQL数据库中的数据拷贝到Oracle中;近期又有需要将一个中型的Oracle数据库拷贝到MySQL中。曾经找过网上各种转换工具,大多收费的,自己写个吧,还一切可控。

转换的前提是两种数据库中已经存在相同的数据结构,可以自己利用SQL语句在目标数据库生成数据结构;或者是使用工具仅生成数据结构(如:DBMover,它是收费的,但可以免费转换数据结构,好像不包括外键,网址:http://dbmover.com/cn/)。

第一个程序,从MySQL拷贝到Oracle

很久以前写的,将一个小型的MySQL数据库中的表拷贝到Oracle数据库中(十万数据量级别,没有优化,大数据量可能很慢):

package com.clzhang.sample.jdbc;

import java.sql.*;

/**
 * 从MySQL数据库拷贝表数据到Oracle数据库中的程序。
 * 前提:两个数据库中都具有相关的表,且表结构相同,目标数据库中还不能存在冲突的数据。
 * @author acer
 *
 */
public class CopyMySQL2Oracle {
    // 源数据库,目标数据库的连接配置
    String mysql_jdbc_url = "jdbc:mysql://localhost/xuejia?user=root&password=password1&useUnicode=true&characterEncoding=gb2312";
    
    String jdbc_url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
    String jdbc_user = "mytest";
    String jdbc_password = "test001";
    
    public void startProcess(String tableName) throws Exception {
        // 创建到两个数据库的连接
        Class.forName("org.gjt.mm.mysql.Driver");
        Connection connSource = DriverManager.getConnection(mysql_jdbc_url);

        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection connDest = DriverManager.getConnection(jdbc_url, jdbc_user,
                jdbc_password);
        
        // 打开源数据库中相关表
        StringBuilder sb = new StringBuilder();
        sb.append("insert into " + tableName + "(");
        Statement stmt= connSource.createStatement();
        ResultSet rs = stmt.executeQuery("select * from " + tableName);
        
        // 显示共计有多少条记录
        rs.last();
        System.out.println(tableName + "表共计有:"+ rs.getRow() + "条记录,正在处理......");
        rs.beforeFirst();
        
        // 先计算目标数据库的PreparedStatement的SQL语句
        ResultSetMetaData rsmd = rs.getMetaData();
        int numberOfColumns = rsmd.getColumnCount();
        for(int i=1; i<=numberOfColumns;i++) {
            sb.append(rsmd.getColumnName(i) + ",");
        }
        sb.deleteCharAt(sb.length()-1);
        sb.append(")values(");
        for(int i=1; i<=numberOfColumns;i++) {
            sb.append("?,");
        }
        sb.deleteCharAt(sb.length()-1);
        sb.append(")");
        System.out.println(sb.toString());
        
        // 给PreparedStatement赋值,然后更新;如果是大数量的情况,可以考虑Batch处理。因为这里的数据量小,直接单条更新了。
        PreparedStatement pstmt = connDest.prepareStatement(sb.toString());
        while(rs.next()) {
            for(int i=1; i<=numberOfColumns;i++) {
                pstmt.setObject(i, rs.getObject(i));
            }
            
            System.out.print("-");
            pstmt.executeUpdate();
        }
        
        // 关闭各资源 
        rs.close();
        stmt.close();
        pstmt.close();
        
        connSource.close();
        connDest.close();
    }

    public static void main(String[] args) throws Exception {
        CopyMySQL2Oracle ins = new CopyMySQL2Oracle();
        ins.startProcess("PRODUCT");
        
        // ...需要拷贝的表名在下面加入即可,注意顺序,比如有外键的表应该排列在主表之后。
    }
}


第二个程序,从Oracle拷贝到MySQL

最近写的,一个中小型数据库(百万级别,做了适当优化,仍旧挺慢的)的拷贝程序,供参考吧。

建议在拷贝之前,禁用、或者是删除目标数据库中的相关索引以提高速度;拷贝完成之后,重新建立索引。

package com.clzhang.sample.jdbc;

import java.sql.*;

/**
 * 这是一个将Oracle数据库中的数据拷贝到MySQL数据库中的简单程序。
 * 仅考虑NUMBER/CHAR/VARCHAR/CLOB/DATE/TIMESTAMP等字段类型。
 * BLOB没有考虑(因为我的数据库中没有BLOB字段,无法测试)。
 * 
 * 前提:两个数据库中都具有相关的表,且表结构相同,目标数据库中还不能存在冲突的数据。
 * @author acer
 *
 */
public class CopyOracle2MySQL {
    // 源数据库,目标数据库的连接配置
    private final String DEST_MYSQL_JDBC_URL = "jdbc:mysql://localhost/mybbs?user=root&password=password1&useUnicode=true&characterEncoding=utf-8";
    
    private final String SOURCE_JDBC_URL = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
    private final String SOURCE_JDBC_USER = "mybbs";
    private final String SOURCE_JDBC_PASSWORD = "bbs001";

    public void startImport() throws Exception {
        // 创建到两个数据库的连接
        Class.forName("org.gjt.mm.mysql.Driver");
        Class.forName("oracle.jdbc.driver.OracleDriver");

        Connection connDest = DriverManager.getConnection(DEST_MYSQL_JDBC_URL);
        Connection connSource = DriverManager.getConnection(SOURCE_JDBC_URL, SOURCE_JDBC_USER,
                SOURCE_JDBC_PASSWORD);
        
        // 查询出当前用户下面的所有表,依次处理(如果有外键,建议人工输入各表,以保证顺序;如果没有外键,直接运行下面程序即可。)
        try {
            
/**            
             // 方式一:自动运行
            Statement stmt = connSource.createStatement();
            ResultSet rs = stmt.executeQuery("select TABLE_NAME from USER_TABLES");
            while(rs.next()) {
                try {
                    importTable(connSource, connDest, rs.getString("TABLE_NAME"));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            rs.close();
            stmt.close();
*/            
            
            // 方式二:人工输入各表名(需要保证顺序,以确保有外键的表在主表之后插入数据)
            importTable(connSource, connDest, "BBSDETAIL");
            importTable(connSource, connDest, "BBSCOMMENT");
        } finally {
            // 自动关闭数据库资源?
            connDest.close();
            connSource.close();
        }
    }
    
    private void importTable(Connection connSource, Connection connDest, String tablename) throws Exception {
        Statement stmt = null;
        PreparedStatement pstmt = null;
        try {
            // 给PreparedStatement赋值,然后更新;如果是大数量的情况,可以考虑Batch处理。因为这里的数据量小,直接单条更新了。
            // 打开源数据库中相关表
            StringBuilder insertSQL = new StringBuilder();
            insertSQL.append("insert into " + tablename + "(");
            stmt= connSource.createStatement();
            ResultSet rs = stmt.executeQuery("select * from " + tablename);
            
            // 先计算目标数据库的PreparedStatement的SQL语句
            ResultSetMetaData rsmd = rs.getMetaData();
            int numberOfColumns = rsmd.getColumnCount();
            for(int i=1; i<=numberOfColumns;i++) {
                insertSQL.append(rsmd.getColumnName(i) + ",");
            }
            insertSQL.deleteCharAt(insertSQL.length()-1);
            insertSQL.append(")values(");
            for(int i=1; i<=numberOfColumns;i++) {
                insertSQL.append("?,");
            }
            insertSQL.deleteCharAt(insertSQL.length()-1);
            insertSQL.append(")");
            System.out.println(insertSQL.toString());
            
            // 计数
            int count = 0;
            // 每多少条记录提交一次,以提高效率
            int batchCount = 1000;
            pstmt = connDest.prepareStatement(insertSQL.toString());
            while(rs.next()) {
                pstmt.clearParameters();
                for(int i=1; i<=numberOfColumns;i++) {
                    if(rsmd.getColumnType(i) == java.sql.Types.NUMERIC) {
                        // 2
                        pstmt.setInt(i, rs.getInt(i));
                    }else if(rsmd.getColumnType(i) == java.sql.Types.DOUBLE) {
                        // 8
                        pstmt.setDouble(i, rs.getDouble(i));
                    }else if(rsmd.getColumnType(i) == java.sql.Types.CHAR
                            || rsmd.getColumnType(i) == java.sql.Types.VARCHAR
                            || rsmd.getColumnType(i) == java.sql.Types.CLOB) {
                        // 1
                        // 12
                        // 2005
                        pstmt.setString(i, rs.getString(i));
                    }else if(rsmd.getColumnType(i) == java.sql.Types.DATE) {
                        // 91
                        pstmt.setDate(i, rs.getDate(i));
                    }else if(rsmd.getColumnType(i) == java.sql.Types.TIMESTAMP) {
                        // 93
                        pstmt.setTimestamp(i, rs.getTimestamp(i));
                    }else {
                        pstmt.setObject(i, rs.getObject(i));
                    }
                }
                pstmt.addBatch();
                
                // 输出统计信息
                count++;
                if(count % batchCount == 0) {
                    // 若干条提交一次
                    System.out.println();
                    System.out.print("正在更新数据库...");
                    pstmt.executeBatch();
                    System.out.println(count);
                }
            }
            if(count % batchCount != 0) {
                // 最后提交一次
                System.out.println();
                System.out.print("正在更新数据库...");
                pstmt.executeBatch();
                System.out.println(count);
            }
            
            rs.close();
        } finally {
            if(stmt != null) stmt.close();
            if(pstmt != null) pstmt.close();
        }
    }
    
    public static void main(String[] args) throws Exception {
        CopyOracle2MySQL ins = new CopyOracle2MySQL();
        ins.startImport();
        
    }
}

 

 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • sql:mysql:函数:TIMESTAMPDIFF函数实现TimeStamp字段相减,求得时间差
    sql:mysql:函数:TIMESTAMPDIFF函数实现TimeS
     函数内指定是minute,则最终结果value值的单位是分钟,如果函数内指定为hours,则最终结果value值单位为小时。//UPLOAD_TIME 减去 CREATE_DTTM 求得时间差,以分钟数计时select avg(TIMESTAMPDIFF(MINUTE,CREATE_DTTM,UPLOAD_TIME)) value,LEFT(CREATE_DTTM
    03-08
  • 去重复的sql(Oracle) 去重复的英文
    1.利用group by 去重复2.可以利用下面的sql去重复,如下  1) select id,name,sex from (select a.*,row_number() over(partition by a.id,a.set order by name) su from test a ) where su=1  2)select id,name,sex from (select a.*,row_number() over(p
    02-10
  • Oracle SQL七次提速技巧
    以下SQL执行时间按序号递减。1,动态SQL,没有绑定变量,每次执行都做硬解析操作,占用较大的共享池空间,若共享池空间不足,会导致其他SQL语句的解析信息被挤出共享池。create or replace procedure proc1as beginfor i in 1..100000 loop    execute imme
    02-10
  • Oracle\SQL  Server等及其他基本语句写法
    Oracle\SQL Server等及其他基本语句写法
    Oracle\SQL  Server等及其他基本语句写法目录一.Excel相关 11.Excel中写脚本范例: 12.提取字节 23. 提取单元格内字符 24.VLOOKUP函数: 2二.SQL语句汇总 21.建表: 22.增 33.删 44.查 65.改 236.Alter的应用 24三.数据库备份与恢复脚本 261. Oracle: 2
    02-10
  • SQL ORACLE case when函数用法
    case when 用法(1)简单case函数:格式:  case 列名   when 条件值1 then 选项1  when 条件值1 then 选项2......  else 默认值 end例如:  select   case job_level  when '1' then '1111'  when '2' then '2222'   when '3' then '3333
    02-10
  • mysql下如何执行sql脚本 执行SQL脚本
    1.编写sql脚本,假设内容如下:  create database dearabao;  use dearabao;  create table niuzi (name varchar(20));  保存脚本文件,假设我把它保存在F盘的hello world目录下,于是该文件的路径为:F:\hello world\niuzi.sql2.执行sql脚本,可以有2种方法: 
    02-10
  • MySQL 5.7版本sql_mode=only_full_group_by问题
    用到GROUP BY 语句查询时com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'col_user_6.a.START_TIME' which is not functionally dependent on colu
    02-10
  • Oracle迁移到MySQL性能下降的注意点 oracle数据
    背景:最近有较多的客户系统由原来由Oracle改造到MySQL后出现了性能问题CPU 100%,或是后台的CRM系统复杂SQL在业务高峰的时候出现堆积导致业务故障。在我的记忆里面淘宝最初从Oracle迁移到MySQL期间也遇到了很多SQL的性能问题,记忆最为深刻的子查询,当初的
    02-10
  • ORACLE中通过SQL语句(alter table)来增加、删除
    1.添加字段:alter table  表名  add (字段  字段类型)  [ default  '输入默认值']  [null/not null]  ;2.添加备注:comment on column  库名.表名.字段名 is  '输入的备注';  如: 我要在ers_data库中  test表 document_type字段添加备注  comm
    02-10
  • MySQL与Oracle 差异比较之六触发器
    触发器编号类别ORACLEMYSQL注释1创建触发器语句不同create or replace trigger TG_ES_FAC_UNIT  before insert or update or delete on ES_FAC_UNIT  for each rowcreate trigger `hs_esbs`.`TG_INSERT_ES_FAC_UNIT` BEFORE INSERT on `hs_esbs`.`es_fac_u
    02-10
点击排行