我们在使用数据库时经常会遇到需要进行数据导入导出的操作,近期使用刚好用到了GreenPlum,因为GreenPlum实际就是对PostgreSQL的封装,所以此经验适用于PostgreSQL及GreenPlum。
在PostgreSQL中装载数据有CopyManager、GpLoad、GreenPlum-Spark-Connector、GpfDist等多种方式,其中GpLoad、GreenPlum-Spark-Connector其实是基于GpfDist来实现的,CopyManager则是依赖于PG的驱动来实现,这里先把CopyManager的基本用法和使用中遇到的问题做个记录。
CopyManager基本用法
binary格式导入的基本用法如下:
String sql = "COPY public.test(a,b,c) FROM STDIN BINARY");PGCopyOutputStream pgCopyOutputStream = new PGCopyOutputStream(conn, sql);DataOutputStream os = new DataOutputStream(pgCopyOutputStream);byte[] header = {'P', 'G', 'C', 'O', 'P', 'Y', 'n', (byte) 0xFF, 'r', 'n', ' '};os.write(header );if (hasOid) { os.writeInt(0);} else { os.writeInt(1);}os.writeInt(0);for(int i = 0; 0 < rows.size(); i++) { os.writeShort(3); //导入字段数 for (int j = 0; j < 3; j++) { if(colValue == null){ os.writeInt(-1); //对应字段无值 }else{ os.writeInt(colLength); //对应字段长度 os.write(colValue); //对应字段值 } }}os.writeShort(-1);os.flush();os.close();conn.commit();
注意点:
1、在上边的代码中conn必须是PgConnnection,如果是用了druid等数据库连接池则需要从相关数据源中拿出原始GpConnection。
2、当某个字段无值时直接在字段长度中写入-1,字段值中不需要写入任何数据。
3、不同类型对应字段长度不同,如short为2、int4为4,int8为8,long为8,double为8,float为4,String为字符串转为byte[]的长度,numeric为8+gpNumeric.getLen()*2。
4、在写字段值时根据不同类型写入方式不同,如int需用writeInt(int),long用writeLong(long),String用write(sting.getBytes())。
5、当conn设置了不自动提交则需要手工提交,手工提交代码需放在os.close()之后,否则会造成锁表。
日期及时间类型处理方式
对于日期及时间类型比较特殊:
Date:该类型需要计算出所设置日期与2000-01-01的天数间隔,以int写入。
Timestamp:该类型需要计算出所设置时间与2000-01-01 :00.000的毫秒间隔*1000,以long写入。
Time:该类型需要计算出所设置时间与:00.000的毫秒间隔*1000,以long写入。
Numeric类型处理方式
当表字段中存在numeric类型的字段时处理比较特殊,其中需要用到的GpNumeric详见(
https://download.csdn.net/download/zhang0114/33805106)。
GpNumeric gpNumeric = new GpNumeric(String.valueOf(srcValue));os.writeInt(8+gpNumeric.getLen()*2);os.writeShort(gpNumeric.getLen());os.writeShort(gpNumeric.getWeight());os.writeShort(gpNumeric.getSig());os.writeShort(gpNumeric.getScale());for(short s : gpNumeric.toShortArray()){ os.writeShort(s);}
?
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!