公司里面对公用数据库的访问有很多限制,因为涉及到性能问题。一般程序用到的就只有几张表。为了更自由地访问数据,一般都需要作数据导出。
用程序实现数据导出,有以下几个问题:
1 数据丢失
用程序导数据,特别是增量导数据,是容易丢失数据的。我的处理方法是利用数据库表的AddTime字段。每次增量导入时,从dest表中取得最大时间,如果不存在(空表),则指定人工指定一个时间点。导入的时间要比最大时间小几秒钟,我定义的是5秒。
2 数据插入冲突
数据插入冲突也是比较容易出现的问题,解决方法是Insert If Not Exist。 对应到sql语句是:
insert into table_name (id,name) select 2,‘a‘ where not exists (select 1 from table_name where id = 2)
3 导入数据的性能
为了提高性能,最好用增量的方式。Java代码如下:
while(rs.next()){ ++queryCount; for(int i=1;i<=count;i++){ destPs.setObject(i, rs.getObject(i)); } destPs.setObject(count+1, rs.getObject(pk)); destPs.addBatch(); if(batchSize%100==0){ destPs.executeBatch(); } } destPs.executeBatch();
4、程序的通用性
一般导数据的逻辑都是一样的,只是表不一样而已。这样的话,在程序实现的时,通用性就显得很重要,不然冗余代码会很多,程序也不好维护。一般的作法是把sql语句抽象出来。Insert语句由表结构生成。生成的Insert语句代码如下:
/* * 生成插入语句 * @param tag 对于设置了主键自动增长的表,需要 * set identity_insert "+tableName+" ON * */ public String sqlGenerate(int count,ResultSetMetaData rsd,String tableName,String pk,boolean tag) throws SQLException{ String sql=""; if(tag){ sql="set identity_insert "+tableName+" ON;"; } sql+=" insert into "+tableName; //columns sql+="("+rsd.getColumnName(1); for(int i=2;i<=count;i++){ sql+=‘,‘; sql+=rsd.getColumnName(i); } sql+=")"; //values sql+="select ?"; for(int i=2;i<=count;i++){ sql+=",?"; } sql+=" where not exists (select 1 from "+tableName+" where "+pk+" = ? )"; return sql; }
这样的话,整个程序就变得很简洁。其实第四点是根据第二点的结构生成的。
用程序实现SQL的表导出
时间: 2024-10-21 06:21:20