最近一直为一件事情很是烦恼,老大让将sqlserver2005中的三个表数据全部都迁移到oracle中,当然,如果表结构都一样,迁移也是很容易的事情,首先建立同样的表机构,写两个数据库连接工具,一个是sqlserver的,一个是oracle的,紧接着,写迁移类,(忘了告诉到家,这三个表中都是有上百万条数据,如果不用批处理的话,时间可想而知了),这个类必须是可以批处理插入的。

   首先写DBUtil数据连接工具。

package com.xqq.DBUtil;


import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.ResultSetMetaData;


public class DBUtil {


private final static String DB_URL = "jdbc:oracle:thin:@192.168.40.37:1521:CSOA";

private final static String DB_DRIVER = "oracle.jdbc.driver.OracleDriver";


private final static String DB_USERNAME = "CSOA";

private final static String DB_PASSWORD = "CSOA";


public static Connection getConnection(){

Connection conn = null;

try{

Class.forName(DB_DRIVER);//反射获得驱动

conn = DriverManager.getConnection(DB_URL,DB_USERNAME,DB_PASSWORD);//建立连接

System.out.println(2);

}catch(Exception e){

e.printStackTrace();

   }

return conn;

}

public void closeConnection(Connection conn){

try{

if(conn!=null){

if(conn!=null){

conn.close();

       }

   }

}catch(Exception e){

e.printStackTrace();

   }

}

//public static void main(String[] args) throws Exception{

Connection connection=DBUtil.getConnection();

//String sql="select * from CCAT_SOSHIKI";

//PreparedStatement smt=(PreparedStatement)connection.prepareStatement(sql);

//ResultSet rs=smt.executeQuery();

//ResultSetMetaData me=rs.getMetaData();

//System.out.println(me.getColumnCount());

//for(int i=1;i<=me.getColumnCount();i++)

//System.out.print(me.getColumnName(i)+"   ");

//while(rs.next()){

//for(int i=1;i<=me.getColumnCount();i++)

//System.out.print(rs.getString(i)+"  ");

//System.out.println();

//System.out.println();

//}

//System.out.println(DBUtil.getConnection());

//}

}

main方法中是测试代码,这里就不多详细介绍了,sqlserver连接工具DBUtil就不多介绍了,因为只需要改一下上面的字段就OK啦。

紧接着,是要写从原数据库中迁移的数据,也即sqlserver SQL语句。


public void convert(String strYMD,String endYMD) {

Hashtable compare = new Hashtable();//建立一个hashtable

String startYMD,enddYMD;

try{

startYMD = new SimpleDateFormat("yyyy-mm-dd").format(new SimpleDateFormat("yyyymmdd").parse(strYMD));

enddYMD = new SimpleDateFormat("yyyy-mm-dd").format(new SimpleDateFormat("yyyymmdd").parse(endYMD));

String sql = "select " +

"FT_EMP_ID," +

"FT_YMD,"+

"FT_TIMEM_No," +

"FT_TYPE,"+

"FT_START_TIME," +

"FT_END_TIME," +

"FT_NOTE," +

"FT_APPROVL_TIME " +

"from T_FINANCE_TIME" +

" where FT_YMD between ? and ?";//取出原表中要用到的字段

System.out.println(sql);

Connection conn1s = DBUtil2.getConnection();//连接sqlserver数据库

PreparedStatement pstmt = conn1s.prepareStatement(sql);//执行查询语句

pstmt.setString(1, startYMD);//(下面的所有语句是对新表中要用到数据编辑)

pstmt.setString(2, enddYMD);

ResultSet rs = pstmt.executeQuery();

System.out.println(sql);

SimpleDateFormat formatDate = new SimpleDateFormat("yyyyMMdd HH:mm:ss");

Calendar c = Calendar.getInstance();

while(rs.next()){

//System.out.println(j++);

T_FINACE_TIME time = new T_FINACE_TIME();

if(rs.getString(1).charAt(0) == 'A'){

time.setCMP_CD("02");

}else

{

time.setCMP_CD("01");

}

time.setFT_EMP_ID(rs.getString(1));

Date date = new SimpleDateFormat("yyyy-mm-dd").parse(rs.getString(2));

if (compare.containsKey(rs.getString(1)+new SimpleDateFormat("yyyymmdd").format(date)+rs.getInt(3))){

System.out.println("comparewain:"+rs.getString(1)+new SimpleDateFormat("yyyymmdd").format(date)+rs.getInt(3));

continue;

}//这段代码很重要,如果有重复的字段,忽略,执行下一条数据。

time.setFT_YMD(new SimpleDateFormat("yyyymmdd").format(date));

//System.out.println(time.getFT_YMD());

time.setFT_TIMEM_No(rs.getInt(3));

//

//if(String.valueOf(Integer.parseInt(rs.getString(4))-131000).charAt(0) != '0'){

//time.setFT_TYPE(String.valueOf((String.valueOf(Integer.parseInt(rs.getString(4))-131000)).charAt(1)));

//}else{

if(rs.getString(4)==null ||rs.getString(4).equals("")){

time.setFT_TYPE("");

}else{

time.setFT_TYPE(String.valueOf(Integer.parseInt(rs.getString(4))-131000));

}

//}

//System.out.println(time.getFT_TYPE());

time.setFT_START_TIME(rs.getString(5));

time.setFT_END_TIME(rs.getString(6));

if (rs.getString(5) == null || rs.getString(5).equals("")

|| rs.getString(6) == null

|| rs.getString(6).equals("")) {

time.setTIME_WK(0);

} else {


time.setTIME_WK((Float.parseFloat(rs.getString(6)) - Float

.parseFloat(rs.getString(5))) / 2);

}

if(rs.getString(7)== null|| rs.getString(7).equals("")){

time.setFT_NOTE("");

}else{

time.setFT_NOTE(rs.getString(7));

}

if(rs.getString(8) == null || rs.getString(7).equals("")){

time.setFT_APPROVL_TIME("");

}else{

Date date1 = new SimpleDateFormat("yyyy-mm-dd").parse(rs.getString(8));

time.setFT_APPROVL_TIME(new SimpleDateFormat("yyyymmdd").format(date1));

}

//System.out.println(time.getFT_APPROVL_TIME());

String s = formatDate.format(c.getTime());

//System.out.println(s);

time.setINS_DATE(formatDate.parse(s));

time.setAPPROVL_KBN("1");

compare.put(rs.getString(1)+new SimpleDateFormat("yyyymmdd").format(date)+rs.getInt(3), "1");//这一步很是关键!

System.out.println(compare.size());

list.add(time);

}

conn1s.close();

System.out.println(list.size());

}catch(Exception e){

e.printStackTrace();

}

}

其中里面很多不同的字段需要转换編輯的,这就不多说了。

下面一步执行转换:

public void execute(Connection conn) {

try {

conn.setAutoCommit(false);

InsertStatement =

"INSERT INTO PQX_EXP" +

"(CMP_CD," +

"USR_ID," +

"REC_YMD," +

"ZHINO," +

"KBN_FINA,"+

"REC_ST_KBN," +

"REC_ET_KBN," +

"TIME_WK,"+

"BIKO," +

"APPROVL_USR,"+

"APPROVL_KBN,"+

"APPROVL_YMD," +

"INS_USERID,"+

"INS_DATE," +

"UP_USERID," +

"UP_DATE)" +

"VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";

PreparedStatement pst = conn.prepareStatement(InsertStatement);

int count = 0;

for (T_FINACE_TIME t_finace_time : list) {

pst.setString(1, t_finace_time.getCMP_CD());

pst.setString(2, t_finace_time.getCMP_CD() + 0

+ t_finace_time.getFT_EMP_ID());

//SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

//String sdate = sdf.format(t_finace_time.getFT_YMD());

pst.setString(3, t_finace_time.getFT_YMD());

pst.setInt(4, t_finace_time.getFT_TIMEM_No());

pst.setString(5, t_finace_time.getFT_TYPE());

pst.setString(6, t_finace_time.getFT_START_TIME());

pst.setString(7, t_finace_time.getFT_END_TIME());

pst.setFloat(8, t_finace_time.getTIME_WK());

pst.setString(9, t_finace_time.getFT_NOTE());

pst.setString(10, t_finace_time.getCMP_CD() + 0

+ t_finace_time.getFT_EMP_ID());

pst.setString(11, t_finace_time.getAPPROVL_KBN());

pst.setString(12, t_finace_time.getFT_APPROVL_TIME());

pst.setString(13, t_finace_time.getCMP_CD() + 0

+ t_finace_time.getFT_EMP_ID());

pst.setDate(14, new java.sql.Date(t_finace_time.getINS_DATE()

.getTime()));

pst.setString(15, t_finace_time.getCMP_CD() + 0

+ t_finace_time.getFT_EMP_ID());

pst.setDate(16, new java.sql.Date(t_finace_time.getINS_DATE()

.getTime()));


pst.addBatch();//执行批处理,如果到了一千条就执行一次,当然效率也是相当快的。

if (++count % bachSize == 0 || count == (list.size()) - 1) {

pst.executeBatch();

conn.commit();

pst.clearBatch();

}

System.out.println(count);

}

pst.close();

conn.close();

} catch (Exception e) {

e.printStackTrace();

}


}

两个方法执行完毕!

这里,主要要强调两个问题,第一,如果,原来数据库中有重复的数据,但现在oracle中不允许有联合关键字重复如何办?我用一个Hashtable保留了数据唯一性(这个问题纠结了几天,老大后来告诉我的)。这样就可以顺利执行啦!

第一次,写这样的博客,写的不好,请多多包含。