同事在迁移数据库时候遇到了一个这样的问题。lang raw字段无法直接从oracle底层进行迁移。我第一次真正见这样的字段。网上搜索一番后,得出了这样的结论。需要通过流处理来从一张表中读取,然后插入另一张表。
起初我尝试了ResultSet.getBinaryStream,ResultSet.getNCharacterStream,这样在插入另一张表的时候如何都不行,最后我尝试了byte数据来获取langRaw字段,最没有希望的尝试竟然成功了。代码如下:
while(rs.next()){
jh=rs.getString("jh");
//is=rs.getBinaryStream("tx");
//Reader reader=rs.getNCharacterStream("tx");
//Reader reader=new InputStreamReader(is);
byte[] b=rs.getBytes("tx");
if(b!=null){
//System.out.println(b);
String sql1="insert into jskg_bak t values(?,?)";
pstmt=conn.prepareStatement(sql1);
pstmt.setString(1, jh);
//pstmt.setCharacterStream(2, reader);
pstmt.setBytes(2, b);
pstmt.executeUpdate();
System.out.println("成功插入一条");
//conn.commit();
}else{
System.out.println("=================="+jh);
String sql1="insert into jskg_bak (jh) values (?)";
pstmt=conn.prepareStatement(sql1);
pstmt.setString(1, jh);
pstmt.executeUpdate();
System.out.println("成功插入一条xxxx");
//conn.commit();
}
if(pstmt!=null){
pstmt.close();
}
}
虽然这样能够取出来,能够插进去,但是我这里有很多张表格,个字段,我不能每个表格做一个程序不是?于是用了下面两个视图。
user_tab_columns从此时图中查询表的列。
user_cons_columns从此时图中查询表的主键。
从这两个视图中查询出我sql需要的东西,于是有了下面的程序,可以自动运行多个表格:
package langraw;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class LangRaw {
/**
* @param args
*/
public static void main(String[] args) {
DBUtil db=new DBUtil();
try {
Connection conn=db.getConnection();
//"JSEA","JSEB","JSEC","JSTB","JSKF","JSZA"
String[] tb={"JSTB"};
for(int i=0;i<tb.length;i++){
String tb_name=tb[i];
getLangRaw(conn,tb_name);
}
System.out.println("==================完成=====================");
} catch (Exception e) {
e.printStackTrace();
}finally{
db.closeConnection();
}
}
//读取字段
public static void getLangRaw(Connection conn,String tb_name){
String jh=null;
String bz=null;
Statement stmt=null;
Statement stmt1=null;
PreparedStatement pstmt=null;
ResultSet rs=null;
ResultSet rs1=null;
try{
stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
stmt1=conn.createStatement();
List<String> listKey=new ArrayList<String>();//表的主键
List<List> listCol=new ArrayList<List>();//表的所有字段
//String sql="select jh,JSZJ from JSYA_OLD t where t.jh not in(select jh from jsya) ";
listKey=getKey(conn, tb_name);
listCol=getCol(conn, tb_name);
String sql="select ";
String str1="";
String str2="";
for(int i=0;i<listCol.size();i++){
if(i!=listCol.size()-1){
str1=str1+listCol.get(i).get(0)+",";
}else if(i==listCol.size()-1){
str1=str1+listCol.get(i).get(0)+" from "+tb_name+"_OLD ";
}
}
String str3="";
for(int j=0;j<listKey.size();j++){
if(listKey.size()==1){
str2="where "+listKey.get(j)+" not in(select "+listKey.get(j)+" from "+tb_name+")";
System.out.println(str2);
}else if(listKey.size()>1){
if(j<listKey.size()-1){
str3=str3+listKey.get(j)+"||";
}else if(j==listKey.size()-1){
str3="where "+str3+listKey.get(j)+" not in (select "+str3+listKey.get(j)+" from "+tb_name+" )";
}
str2=str3;
}
}
//sql=sql+str1+str2+" where JH not in(select JH from "+tb_name+")";
String sql4="SELECT A.*, ROWNUM RN FROM (";
String sql5=") A WHERE ROWNUM <= 100";
sql=sql4+sql+str1+str2+sql5;
String sql0="select count(*) as num from ("+sql+str1+str2+")";
System.out.println(sql);
rs1=stmt1.executeQuery(sql0);
int num=0;
while(rs1.next()){
num=rs.getInt("num");
}
if(num%100!=0){
num=num/100+1;
}
for(int l=0;l<num;l++){
///循环页
rs=stmt.executeQuery(sql);
// rs.setFetchSize(10);
int o=0;
while(rs.next()){
o++;
System.out.println(o);
String sql1="insert into "+tb_name+" values(";
String str="";
for(int m=0;m<listCol.size();m++){
if(m<listCol.size()-1){
str=str+"?,";
}else if(m==listCol.size()-1){
str=str+"?)";
}
}
sql1=sql1+str;
pstmt=conn.prepareStatement(sql1);
for(int n=0;n<listCol.size();n++){
//System.out.println(listCol.get(n).get(0));
//System.out.println(listCol.get(n).get(1));
if(listCol.get(n).get(1).equals("LONG RAW")){
byte[] b=rs.getBytes(listCol.get(n).get(0).toString());
pstmt.setBytes(n+1,b);
b=null;
}else if(listCol.get(n).get(1).equals("DATE")){
pstmt.setDate(n+1, rs.getDate(listCol.get(n).get(0).toString()));
}else if(listCol.get(n).get(1).equals("NUMBER")){
pstmt.setDouble(n+1, rs.getInt(listCol.get(n).get(0).toString()));
}else{
pstmt.setString(n+1, rs.getString(listCol.get(n).get(0).toString()));
}
}
System.out.println(sql1);
pstmt.executeUpdate();
rs.moveToCurrentRow();
//System.out.println("成功插入一条");
conn.commit();
//pstmt.clearParameters();
//if(pstmt!=null){
pstmt.close();
//}
}}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(rs!=null){
rs.close();
}if(stmt!=null){
stmt.close();
}}catch(Exception e){
e.printStackTrace();
}
}
}
//查询表的主键
public static List<String> getKey(Connection conn,String tb_name){
Statement stmt=null;
ResultSet rs=null;
List<String> listKey=new ArrayList<String>();
String sql="select column_name from sys.user_cons_columns t where t.table_name='"+tb_name+"_OLD' and t.position is not null";
try {
stmt=conn.createStatement();
rs=stmt.executeQuery(sql);
while(rs.next()){
listKey.add(rs.getString("column_name"));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
if(rs!=null){
rs.close();
}
if(stmt!=null){
stmt.close();
}
}catch (SQLException e) {
e.printStackTrace();
}
}
return listKey;
}
//查询表的所有列
public static List<List> getCol(Connection conn,String tb_name){
Statement stmt=null;
ResultSet rs=null;
List<List> listCol=new ArrayList<List>();
String sql="select COLUMN_NAME,DATA_TYPE from sys.user_tab_columns t where t.TABLE_NAME='"+tb_name+"_OLD' order by t.COLUMN_ID";
try {
stmt=conn.createStatement();
rs=stmt.executeQuery(sql);
while(rs.next()){
List<String> listColNameType=new ArrayList<String>();
listColNameType.add(rs.getString("COLUMN_NAME"));
listColNameType.add(rs.getString("DATA_TYPE"));
listCol.add(listColNameType);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
if(rs!=null){
rs.close();
}
if(stmt!=null){
stmt.close();
}
}catch (SQLException e) {
e.printStackTrace();
}
}
return listCol;
}
}
上面这个程序时分页查询,然后取的langraw字段。其实在这之前我陷入了下面这个误区:
运行这个程序的时候,问题又遇到了,那就是 ResultSet结果集实在时太大了,跑上几百条就内存溢出。
这时我也陷入了这个问题里面,总想找个方法,能够循环一行,释放一条rs,结果自然可以想到。呵呵
另外需要注意的是,ResultSet的next方法用的时候,你要明确怎么指向,上面程序里在new statement的时候指定了参数,至于参数的意思,网上很多介绍的。