在GaussDB中,COPY命令是高效传输数据的工具,支持在数据库表与文件系统之间批量导入_导出数据
在GaussDB中,COPY命令是高效传输数据的工具,支持在数据库表与文件系统之间批量导入/导出数据。通过JDBC调用COPY命令,可在Java应用中实现数据的高效迁移。以下从核心语法、JDBC操作流程、示例代码及注意事项四方面详细介绍。
一、COPY命令核心语法
COPY命令分为导入(COPY IN)和导出(COPY OUT)两种模式,支持本地(客户端)或服务端文件路径,并可指定数据格式(如TEXT、CSV、BINARY)及多种选项(如分隔符、编码)。
- 导入数据(COPY IN)
将文件数据加载到数据库表中,语法:
COPY [ONLY] table_name [(column_list)]
FROM {'file_path' | PROGRAM 'command' | STDIN}
[WITH]
(
FORMAT format_type,
DELIMITER 'delimiter_char',
HEADER [boolean],
ENCODING 'encoding_name',
QUOTE 'quote_char',
ESCAPE 'escape_char',
NULL [AS 'null_string'],
... -- 其他可选参数
);
ONLY:仅导入指定表,不包含继承表(可选)。
file_path:服务端文件路径(需数据库服务器有权限访问);STDIN表示从客户端输入流读取(需配合JDBC流操作)。
FORMAT:支持TEXT(默认,逗号分隔)、CSV(符合RFC 4180)、BINARY(二进制格式)。
2. 导出数据(COPY OUT)
将表数据导出到文件,语法:
COPY [ONLY] table_name [(column_list)]
TO {'file_path' | STDOUT}
[WITH]
(
FORMAT format_type,
DELIMITER 'delimiter_char',
HEADER [boolean],
ENCODING 'encoding_name',
... -- 其他可选参数
);
STDOUT:输出到客户端输出流(需配合JDBC流读取)。
二、JDBC中执行COPY的关键步骤
通过JDBC执行COPY命令的核心是利用java.sql.Statement或PreparedStatement执行SQL语句。需注意:
权限要求:数据库用户需具备目标表的SELECT(导出)或INSERT(导入)权限,以及对文件路径的读写权限(服务端模式)。
文件路径:服务端模式下,file_path需为数据库服务器的绝对路径(如/data/load.csv);客户端模式下可使用STDIN/STDOUT通过流传输。
事务控制:COPY命令默认在事务中执行,若需自动提交可设置autoCommit=true(或显式commit())。
三、JDBC导入/导出示例
以下以GaussDB兼容PostgreSQL的JDBC驱动(如postgresql-connector-java-x.x.x.jar)为例,演示Java代码实现。
- 导入数据(COPY FROM LOCAL FILE)
将客户端本地文件/data/input.csv导入到数据库表user_info。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class CopyImportExample {
public static void main(String[] args) {
String jdbcUrl = "jdbc:postgresql://gaussdb-host:port/dbname";
String user = "username";
String password = "password";
try (Connection conn = DriverManager.getConnection(jdbcUrl, user, password);
Statement stmt = conn.createStatement()) {
// 导入CSV文件到表user_info(假设表有id,name,age三列)
String copySql = "COPY user_info (id, name, age) " +
"FROM LOCAL '/data/input.csv' " + // LOCAL指定客户端文件
"WITH (FORMAT CSV, HEADER true, DELIMITER ',')";
int rowsAffected = stmt.executeUpdate(copySql);
System.out.println("导入成功,影响行数:" + rowsAffected);
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 导出数据(COPY TO LOCAL FILE)
将数据库表user_info的数据导出到客户端本地文件/data/output.csv。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class CopyExportExample {
public static void main(String[] args) {
String jdbcUrl = "jdbc:postgresql://gaussdb-host:port/dbname";
String user = "username";
String password = "password";
try (Connection conn = DriverManager.getConnection(jdbcUrl, user, password);
Statement stmt = conn.createStatement()) {
// 导出表user_info到CSV文件(带表头)
String copySql = "COPY user_info TO LOCAL '/data/output.csv' " +
"WITH (FORMAT CSV, HEADER true, DELIMITER ',')";
int rowsAffected = stmt.executeUpdate(copySql);
System.out.println("导出成功,影响行数:" + rowsAffected);
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 高级场景:通过流传输(STDIN/STDOUT)
若需通过Java流(而非本地文件)传输数据,可使用STDIN(导入)或STDOUT(导出)配合PGConnection的流操作(GaussDB JDBC驱动扩展)。
示例:通过InputStream导入数据到表
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import org.postgresql.copy.CopyIn;
import org.postgresql.copy.CopyManager;
import org.postgresql.core.BaseConnection;
public class CopyFromStreamExample {
public static void main(String[] args) {
String jdbcUrl = "jdbc:postgresql://gaussdb-host:port/dbname";
String user = "username";
String password = "password";
String tableName = "user_info";
String filePath = "/data/input.csv";
try (Connection conn = DriverManager.getConnection(jdbcUrl, user, password)) {
// 获取CopyManager实例(PostgreSQL扩展)
CopyManager copyManager = new CopyManager((BaseConnection) conn);
// 从文件创建输入流
InputStream inputStream = new FileInputStream(filePath);
// 执行COPY IN(从流导入)
String copyCommand = String.format(
"COPY %s (id, name, age) FROM STDIN WITH (FORMAT CSV, HEADER true, DELIMITER ',')",
tableName
);
long rowsCopied = copyManager.copyIn(copyCommand, inputStream);
System.out.println("流导入成功,行数:" + rowsCopied);
} catch (Exception e) {
e.printStackTrace();
}
}
}
示例:通过OutputStream导出数据到流
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import org.postgresql.copy.CopyOut;
import org.postgresql.copy.CopyManager;
import org.postgresql.core.BaseConnection;
public class CopyToStreamExample {
public static void main(String[] args) {
String jdbcUrl = "jdbc:postgresql://gaussdb-host:port/dbname";
String user = "username";
String password = "password";
String tableName = "user_info";
String filePath = "/data/output.csv";
try (Connection conn = DriverManager.getConnection(jdbcUrl, user, password)) {
CopyManager copyManager = new CopyManager((BaseConnection) conn);
// 创建输出流
OutputStream outputStream = new FileOutputStream(filePath);
// 执行COPY OUT(导出到流)
String copyCommand = String.format(
"COPY %s TO STDOUT WITH (FORMAT CSV, HEADER true, DELIMITER ',')",
tableName
);
long rowsCopied = copyManager.copyOut(copyCommand, outputStream);
System.out.println("流导出成功,行数:" + rowsCopied);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
四、注意事项
文件路径权限:服务端模式下,数据库服务器需有读取/写入file_path的权限(如/data/目录需gaussdb用户可访问)。
数据格式匹配:导入时需确保文件列数、顺序与表结构一致(或通过column_list指定列);CSV需注意转义符(如引号"处理)。
字符编码:建议显式指定ENCODING(如UTF8),避免乱码(默认使用数据库编码)。
大对象支持:BINARY格式适用于二进制数据(如图像),但需谨慎使用(体积大且解析复杂)。
事务回滚:若COPY执行后未提交事务,可通过conn.rollback()回滚(仅当autoCommit=false时有效)。
驱动版本:确保使用GaussDB兼容的JDBC驱动(如postgresql-connector-java-42.x.x.jar),部分高级功能(如流操作)依赖驱动扩展类(如CopyManager)。
总结
通过JDBC调用GaussDB的COPY命令,可高效实现大数据量的导入导出。核心是利用Statement执行COPY SQL语句,或通过CopyManager结合流操作处理非文件场景。需注意文件路径权限、数据格式匹配及驱动兼容性,以确保操作成功。