PostgreSQL教程FG035-PG数据导出/导入:COPY语句核心用法
本文档风哥主要介绍PostgreSQL教程035相关内容。风哥教程参考PostgreSQL官方文档Server Administration, SQL Language内容编写,适合DBA人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。
1. COPY语句概述
COPY语句是PostgreSQL中用于高效数据导入导出的核心命令,它可以在表和文件之间快速传输大量数据。COPY命令比INSERT语句性能更高,特别适合批量数据操作。
2. COPY语句基本语法
COPY语句支持两种主要用法:从表导出数据到文件,以及从文件导入数据到表。
FROM {‘filename’ | PROGRAM ‘command’ | STDIN}
[WITH (option [, …])]
COPY {table_name [(column1, column2, …)] | (query)}
TO {‘filename’ | PROGRAM ‘command’ | STDOUT}
[WITH (option [, …])]
3. 从表导出数据到文件
首先创建测试表并插入数据:
from oracle:www.itpux.com
CREATE TABLE fgedu_products (
product_id SERIAL PRIMARY KEY,
product_name VARCHAR(200) NOT NULL,
category VARCHAR(50),
price NUMERIC(10,2),
stock INTEGER DEFAULT 0,
created_date DATE DEFAULT CURRENT_DATE
);
— 插入测试数据
INSERT INTO fgedu_products (product_name, category, price, stock) VALUES
(‘笔记本电脑’, ‘电子产品’, 5999.00, 50),
(‘无线鼠标’, ‘电子产品’, 99.00, 200),
(‘机械键盘’, ‘电子产品’, 399.00, 150),
(‘显示器’, ‘电子产品’, 1299.00, 80),
(‘办公椅’, ‘办公用品’, 899.00, 100);
执行结果:
将表数据导出到CSV文件:
COPY fgedu_products TO ‘/tmp/products.csv’ WITH (FORMAT CSV, HEADER);
执行结果:
查看导出的CSV文件内容:
\! cat /tmp/products.csv
执行结果:
1,笔记本电脑,电子产品,5999.00,50,2026-04-04
2,无线鼠标,电子产品,99.00,200,2026-04-04
3,机械键盘,电子产品,399.00,150,2026-04-04
4,显示器,电子产品,1299.00,80,2026-04-04
5,办公椅,办公用品,899.00,100,2026-04-04
导出特定列的数据:
COPY fgedu_products (product_name, price) TO ‘/tmp/products_simple.csv’
WITH (FORMAT CSV, HEADER);
执行结果:
使用查询结果导出数据:
COPY (
SELECT product_name, category, price
FROM fgedu_products
WHERE price > 500
ORDER BY price DESC
) TO ‘/tmp/expensive_products.csv’ WITH (FORMAT CSV, HEADER);
执行结果:
4. 从文件导入数据到表
创建新的产品表用于导入测试:
CREATE TABLE fgedu_products_import (
product_id INTEGER,
product_name VARCHAR(200),
category VARCHAR(50),
price NUMERIC(10,2),
stock INTEGER,
created_date DATE
);
从CSV文件导入数据:
COPY fgedu_products_import FROM ‘/tmp/products.csv’ WITH (FORMAT CSV, HEADER);
执行结果:
验证导入的数据:
SELECT * FROM fgedu_products_import;
执行结果:
————+————–+———–+——–+——-+————-
1 | 笔记本电脑 | 电子产品 | 5999.00| 50 | 2026-04-04
2 | 无线鼠标 | 电子产品 | 99.00| 200 | 2026-04-04
3 | 机械键盘 | 电子产品 | 399.00| 150 | 2026-04-04
4 | 显示器 | 电子产品 | 1299.00| 80 | 2026-04-04
5 | 办公椅 | 办公用品 | 899.00| 100 | 2026-04-04
(5 rows)
创建包含特殊字符的测试数据:
\! cat > /tmp/products_special.csv << 'EOF' product_name,category,price,stock "笔记本电脑,Pro",电子产品,6999.00,30 "无线鼠标""高级版""",电子产品,199.00,50 机械键盘,电子产品,399.00,150 EOF
创建测试表并导入包含特殊字符的数据:
CREATE TABLE fgedu_products_special (
product_name VARCHAR(200),
category VARCHAR(50),
price NUMERIC(10,2),
stock INTEGER
);
— 导入包含特殊字符的数据
COPY fgedu_products_special FROM ‘/tmp/products_special.csv’
WITH (FORMAT CSV, HEADER);
执行结果:
验证导入的数据:
SELECT * FROM fgedu_products_special;
执行结果:
更多学习教程公众号风哥教程itpux_com
——————-+———–+——–+——-
笔记本电脑,Pro | 电子产品 | 6999.00| 30
无线鼠标”高级版” | 电子产品 | 199.00| 50
机械键盘 | 电子产品 | 399.00| 150
(3 rows)
5. COPY语句高级选项
使用DELIMITER选项指定分隔符:
COPY fgedu_products TO ‘/tmp/products_tab.txt’
WITH (FORMAT text, DELIMITER E’\t’, HEADER);
执行结果:
查看导出的制表符分隔文件:
\! cat /tmp/products_tab.txt
执行结果:
1 笔记本电脑 电子产品 5999.00 50 2026-04-04
2 无线鼠标 电子产品 99.00 200 2026-04-04
3 机械键盘 电子产品 399.00 150 2026-04-04
4 显示器 电子产品 1299.00 80 2026-04-04
5 办公椅 办公用品 899.00 100 2026-04-04
使用NULL选项处理NULL值:
CREATE TABLE fgedu_products_null (
product_id SERIAL PRIMARY KEY,
product_name VARCHAR(200),
category VARCHAR(50),
price NUMERIC(10,2),
description TEXT
);
— 插入包含NULL值的数据
INSERT INTO fgedu_products_null (product_name, category, price, description) VALUES
(‘笔记本电脑’, ‘电子产品’, 5999.00, ‘高性能笔记本’),
(‘无线鼠标’, NULL, 99.00, ‘无线连接’),
(‘机械键盘’, ‘电子产品’, NULL, ‘机械轴体’),
(‘显示器’, ‘电子产品’, 1299.00, NULL);
执行结果:
导出数据时指定NULL值的表示方式:
COPY fgedu_products_null TO ‘/tmp/products_null.csv’
WITH (FORMAT CSV, HEADER, NULL ‘NULL’);
执行结果:
更多视频教程www.fgedu.net.cn
查看导出的文件:
执行结果:
1,笔记本电脑,电子产品,5999.00,高性能笔记本
2,无线鼠标,NULL,99.00,无线连接
3,机械键盘,电子产品,NULL,机械轴体
4,显示器,电子产品,1299.00,NULL
使用ENCODING选项处理字符编码:
COPY fgedu_products TO ‘/tmp/products_utf8.csv’
WITH (FORMAT CSV, HEADER, ENCODING ‘UTF8’);
执行结果:
使用QUOTE和ESCAPE选项处理特殊字符:
\! cat > /tmp/products_quote.csv << 'EOF' id,name,description 1,"产品A","这是""产品A""的描述" 2,"产品B,特别版","包含逗号的产品" 3,"产品C","包含\n换行符的产品" EOF -- 创建测试表 CREATE TABLE fgedu_products_quote ( id INTEGER, name VARCHAR(200), description TEXT ); -- 导入数据,指定引号和转义字符 COPY fgedu_products_quote FROM '/tmp/products_quote.csv' WITH (FORMAT CSV, HEADER, QUOTE '"', ESCAPE '"');
执行结果:
学习交流加群风哥QQ113257174
验证导入的数据:
执行结果:
—-+————–+——————————
1 | 产品A | 这是”产品A”的描述
2 | 产品B,特别版 | 包含逗号的产品
3 | 产品C | 包含
换行符的产品
(3 rows)
6. COPY与\copy命令的区别
COPY命令和\copy命令的主要区别在于执行位置和权限要求:
— 示例:
COPY fgedu_products TO ‘/tmp/products_server.csv’ WITH (FORMAT CSV, HEADER);
— \copy命令:在客户端执行,普通用户也可以使用
— 示例:
\copy fgedu_products TO ‘/tmp/products_client.csv’ WITH (FORMAT CSV, HEADER)
执行结果:
COPY 5
— \copy命令执行结果
COPY 5
使用\copy命令从STDIN导入数据:
CREATE TABLE fgedu_products_stdin (
product_name VARCHAR(200),
price NUMERIC(10,2)
);
— 使用\copy从标准输入导入数据
\copy fgedu_products_stdin FROM STDIN WITH (FORMAT CSV)
输入数据(按Ctrl+D结束):
产品A,199.00
产品B,299.00
产品C,399.00
\.
执行结果:
学习交流加群风哥微信: itpux-com
验证导入的数据:
执行结果:
————–+——–
产品A | 199.00
产品B | 299.00
产品C | 399.00
(3 rows)
7. 实战案例:批量数据迁移
模拟从旧系统迁移数据到新系统的场景:
CREATE TABLE fgedu_old_orders (
order_id INTEGER,
customer_id INTEGER,
order_date DATE,
amount NUMERIC(10,2),
status VARCHAR(20)
);
— 插入旧系统数据
INSERT INTO fgedu_old_orders VALUES
(1001, 1, ‘2026-01-15’, 5999.00, ‘completed’),
(1002, 2, ‘2026-01-16’, 99.00, ‘completed’),
(1003, 3, ‘2026-01-17’, 399.00, ‘shipped’),
(1004, 1, ‘2026-01-18’, 1299.00, ‘processing’),
(1005, 4, ‘2026-01-19’, 899.00, ‘pending’);
执行结果:
导出旧系统数据:
COPY fgedu_old_orders TO ‘/tmp/old_orders.csv’ WITH (FORMAT CSV, HEADER);
执行结果:
创建新系统表结构:
CREATE TABLE fgedu_new_orders (
order_id SERIAL PRIMARY KEY,
customer_id INTEGER,
order_date DATE,
amount NUMERIC(10,2),
status VARCHAR(20),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
导入数据到新系统:
COPY fgedu_new_orders (order_id, customer_id, order_date, amount, status)
FROM ‘/tmp/old_orders.csv’ WITH (FORMAT CSV, HEADER);
执行结果:
验证迁移的数据:
风哥提示:
SELECT * FROM fgedu_new_orders;
执行结果:
———-+————-+————+———+————+————————–+————————–
1001 | 1 | 2026-01-15 | 5999.00 | completed | 2026-04-04 10:30:45.123 | 2026-04-04 10:30:45.123
1002 | 2 | 2026-01-16 | 99.00 | completed | 2026-04-04 10:30:45.124 | 2026-04-04 10:30:45.124
1003 | 3 | 2026-01-17 | 399.00 | shipped | 2026-04-04 10:30:45.125 | 2026-04-04 10:30:45.125
1004 | 1 | 2026-01-18 | 1299.00 | processing | 2026-04-04 10:30:45.126 | 2026-04-04 10:30:45.126
1005 | 4 | 2026-01-19 | 899.00 | pending | 2026-04-04 10:30:45.127 | 2026-04-04 10:30:45.127
(5 rows)
数据迁移统计:
SELECT
COUNT(*) AS total_orders,
SUM(amount) AS total_amount,
AVG(amount) AS avg_amount,
MAX(amount) AS max_amount,
MIN(amount) AS min_amount
FROM fgedu_new_orders;
执行结果:
————–+————–+————-+————+————
5 | 8695.00 | 1739.000000 | 5999.00 | 99.00
(1 row)
8. 常见问题与解决方案
问题1:权限不足错误
COPY fgedu_products TO ‘/tmp/test.csv’ WITH (FORMAT CSV);
错误信息:
HINT: Anyone can COPY to stdout or from stdin. psql’s \copy command also works for anyone.
解决方案:使用\copy命令
\copy fgedu_products TO ‘/tmp/test.csv’ WITH (FORMAT CSV)
执行结果:
问题2:数据类型不匹配
\! cat > /tmp/products_error.csv << 'EOF' product_name,price 产品A,199.00 产品B,invalid_price 产品C,399.00 EOF -- 尝试导入错误数据 CREATE TABLE fgedu_products_error ( product_name VARCHAR(200), price NUMERIC(10,2) ); COPY fgedu_products_error FROM '/tmp/products_error.csv' WITH (FORMAT CSV, HEADER);
错误信息:
CONTEXT: COPY fgedu_products_error, line 3, column price: “invalid_price”
解决方案:使用ON_ERROR选项(PostgreSQL 14+)
COPY fgedu_products_error FROM ‘/tmp/products_error.csv’
WITH (FORMAT CSV, HEADER, ON_ERROR ignore);
执行结果:
验证导入的数据:
执行结果:
————–+——–
产品A | 199.00
产品C | 399.00
(2 rows)
问题3:文件路径问题
COPY fgedu_products TO ‘products.csv’ WITH (FORMAT CSV);
错误信息:
HINT: Use an absolute path or COPY to stdout.
解决方案:使用绝对路径
COPY fgedu_products TO ‘/tmp/products_absolute.csv’ WITH (FORMAT CSV);
执行结果:
问题4:编码问题
\! iconv -f UTF-8 -t GBK << 'EOF' > /tmp/products_gbk.csv
product_name,price
产品A,199.00
产品B,299.00
EOF
— 尝试导入GBK编码的文件
CREATE TABLE fgedu_products_gbk (
product_name VARCHAR(200),
price NUMERIC(10,2)
);
COPY fgedu_products_gbk FROM ‘/tmp/products_gbk.csv’
WITH (FORMAT CSV, HEADER, ENCODING ‘GBK’);
执行结果:
验证导入的数据:
执行结果:
————–+——–
产品A | 199.00
产品B | 299.00
(2 rows)
9. 清理环境
清理测试表和文件:
DROP TABLE IF EXISTS fgedu_products;
DROP TABLE IF EXISTS fgedu_products_import;
DROP TABLE IF EXISTS fgedu_products_special;
DROP TABLE IF EXISTS fgedu_products_null;
DROP TABLE IF EXISTS fgedu_products_quote;
DROP TABLE IF EXISTS fgedu_products_stdin;
DROP TABLE IF EXISTS fgedu_old_orders;
DROP TABLE IF EXISTS fgedu_new_orders;
DROP TABLE IF EXISTS fgedu_products_error;
DROP TABLE IF EXISTS fgedu_products_gbk;
— 删除测试文件
\! rm -f /tmp/products*.csv /tmp/products*.txt /tmp/old_orders.csv
执行结果:
DROP TABLE
DROP TABLE
DROP TABLE
DROP TABLE
DROP TABLE
DROP TABLE
DROP TABLE
DROP TABLE
DROP TABLE
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
