MySQL与Oracle之间互相拷贝数据的Java程序
因为工作需要,先是需要将一个小型的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) {
//
pstmt.setInt(i, rs.getInt(i));
}else if(rsmd.getColumnType(i) == java.sql.Types.DOUBLE) {
//
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
//
pstmt.setString(i, rs.getString(i));
}else if(rsmd.getColumnType(i) == java.sql.Types.DATE) {
//
pstmt.setDate(i, rs.getDate(i));
}else if(rsmd.getColumnType(i) == java.sql.Types.TIMESTAMP) {
//
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(); }
}
MySQL与Oracle之间互相拷贝数据的Java程序的更多相关文章
- 三分钟带你分清Mysql 和Oracle之间的误区
摘要:Mysql 和Oracle,别再傻傻分不清. mysql 和Oracle 在开发中的使用是随处可见的,那就简单去了解一下这俩款火的不行的数据库. 本质区别: Oracle数据库是一个对象关系数据 ...
- [转]MYSQL 与 Oracle 之间的数据类型转换
原文地址:http://www.cnblogs.com/guyueyanzi/archive/2010/02/27/1674788.html Table 2-4 Default Data Type M ...
- Mysql与Oracle之间的数据类型转换
MySQL Data Type Oracle Data Type BIGINT NUMBER(19, 0) BIT RAW BLOB BLOB, RAW CHAR CHAR DATE DATE DAT ...
- mysql从一个表中拷贝数据到另一个表中sql语句
这一段在找新的工作,今天面试时,要做一套题,其中遇到这么一句话,从一个表中拷贝所有的数据到另一个表中的sql是什么? 原来我很少用到,也没注意过这个问题,面试后我上网查查,回来自己亲手写了写,测试了下 ...
- 项目mysql数据导入数据的Java程序
最近写的一个数据库导入数据的程序,有兴趣的同学可以参考一下: 这个程序是针对mysql数据库的,在本地或服务器上运行,主要的需求还是,针对项目的某些bug修复 后,客户的数据要搬到新表上来,避免新版本 ...
- XML转换成TXT行数据的Java程序
ZKe ------------------- XML数据的一个块内的所有属性,转换成TXT文件的一行.众所周知XML文件是通过类似HTML的标签进行数据的定义如图所示 属性由id, article, ...
- mysql类似oracle rownum写法
rownum是oracle才有的写法,rownum在oracle中可以用于取第一条数据,或者批量写数据时限定批量写的数量等 mysql取第一条数据写法 SELECT * FROM t order by ...
- JDBC Java 程序从 MySQL 数据库中读取数据,并备份到 xml 文档中
MySQL 版本:Server version: 5.7.17-log MySQL Community Server (GPL) 相关内容:JDBC Java 程序从 MySQL 数据库中读取数据,并 ...
- 一种从JSON数据创建Java类的高效办法
<一种从JSON数据创建Java类的高效办法> 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs JSON格式的数据经常会遇到,比如调用Web服 ...
随机推荐
- SpringBoot引入freemaker前端模板
1.引入freeMarker的依赖包 <!-- 引入freeMarker的依赖包. --> <dependency> <groupId>org.springfram ...
- 【Zookeeper】源码分析之Watcher机制(二)之WatchManager
一.前言 前面已经分析了Watcher机制中的第一部分,即在org.apache.zookeeper下的相关类,接着来分析org.apache.zookeeper.server下的WatchManag ...
- http协议版本历史
1.http 0.9 2.http 1.0 3. http 1.1 4.http 2.0 推送:主动发送js.css推送到浏览器. 二进制流:可以并行发送数据. 2019.3.18补充: (1)htt ...
- 绑定域名到JavaWeb项目,由域名直接访问到网站首页
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6383996.html 一:购买域名 请移步到相关网站购买域名,我是在腾讯云买的.购买后记得实名认证,不然解析不 ...
- tensorflow serving 编写配置文件platform_config_file的方法
1.安装grpc gRPC 的安装: $ pip install grpcio 安装 ProtoBuf 相关的 python 依赖库: $ pip install protobuf 安装 python ...
- Laravel返回不重复的某个字段信息列表
->groupBy('brand_id') ->pluck('brand_id');
- 〖Linux〗svn log 每个日志记录只显示一行的方法
vi ~/.bashrc,增加一个function svnlog(){ svn log "$@" | awk -f <(cat <<EOF #!/usr/bin/ ...
- Resources.class.getResourceAsStream 获取配置的方法
转载:https://blog.csdn.net/dwl764457208/article/details/78593005 有空可以看这个: 类加载器与 Class.getResourceAsStr ...
- gnu screen的用法
在使用ssh或者telnet登录远程主机后执行一些耗时的命令, 如果此时ssh或者telnet中断, 那么远程主机上正在执行的程序或者说命令也会被迫终止. screen能够很好地解决这个问题, scr ...
- Spring+Quartz实现动态添加定时任务
发布时间:2018-12-03 技术:spring4.0.2+quartz2.2.1 概述 在最近工作中,由于涉及到定时任务特别多,而这些工作又是由下属去完成的,在生成环境中经常会出现业务逻辑 ...