最常见的报错是类型不匹配和空值处理不当:csv中日期字符串需显式转为date类型,""、"null"等须映射为python none,否则触发invalid input syntax;建议用pandas统一清洗并校验字段长度与表结构对齐。

用 psycopg2 批量插入前先清理数据类型
直接 copy_from 或 execute_batch 往 PostgreSQL 插入 CSV 数据,最常见的报错是类型不匹配——比如 CSV 里写的是 "2024-01-01",但目标字段是 DATE,而 psycopg2 默认不会自动转换字符串。更麻烦的是空值:""、"NULL"、"N/A" 都得手动映射成 Python 的 None,否则会触发 invalid input syntax for type 错误。
实操建议:
- 用
pandas.read_csv(..., na_values=["", "NULL", "N/A"], keep_default_na=True)统一转空值 - 对时间列显式调用
pd.to_datetime(df["col"], errors="coerce"),失败变NaT(自动转为None) - 数值列用
pd.to_numeric(df["col"], errors="coerce"),避免字符串如"1,234"导致插入失败 - 插入前检查
df.dtypes,和 PostgreSQL 表结构对齐,尤其注意object列是否真该是文本
用 copy_from 比 execute_batch 快 5–10 倍,但有前提
copy_from 是 PostgreSQL 原生命令封装,绕过 SQL 解析,适合纯数据导入;但它要求输入是类文件对象,且每行必须严格对应表字段顺序和类型,不支持字段映射或条件过滤。
实操建议:
- 用
StringIO构造内存文件流:先df.to_csv(index=False, header=False, date_format="%Y-%m-%d"),再传给copy_from - 确保 CSV 不含 BOM、换行符在字段内(用
quoting=csv.QUOTE_MINIMAL导出更安全) - 如果表有自增主键,CSV 中对应列必须留空或填
NULL,不能传字符串"NULL"(那是字面量) - 别在事务外调用
copy_from—— 出错时整个批次回滚,比单条插入更容易定位问题行
遇到 psycopg2.errors.StringDataRightTruncation 怎么办
这是 PostgreSQL 报的「字符串超长」错误,常见于 CSV 字段内容比表定义的 VARCHAR(n) 长。它不会告诉你哪一行、哪个字段越界,只报错位置模糊。
实操建议:
- 提前查表结构:
SELECT column_name, character_maximum_length FROM information_schema.columns WHERE table_name = 'your_table' - 用
df[col].str.len().max()检查每列实际最大长度,比定义长度多留 10% 余量 - 临时扩字段:
ALTER TABLE your_table ALTER COLUMN col TYPE VARCHAR(500)(别用TEXT图省事,索引和排序性能会掉) - 导入后用
SELECT col, LENGTH(col) FROM your_table ORDER BY LENGTH(col) DESC LIMIT 5快速验证
并发导入多个 CSV 文件时连接和事务怎么管
用同一个 psycopg2.connect() 对象在多线程里共享游标会出错;而每个文件都开新连接又容易打满数据库连接池。更隐蔽的问题是:一个文件导入失败,其他文件不该自动回滚——它们是独立批次。
实操建议:
- 每个文件用独立
connection+cursor,用with确保关闭:with psycopg2.connect(...) as conn: - 禁用自动提交:
conn.autocommit = False,并在成功后显式conn.commit() - 用
concurrent.futures.ThreadPoolExecutor(max_workers=3)控制并发数,避免压垮 PostgreSQL 的max_connections - 文件名带时间戳或哈希值,失败时把报错和文件路径一起记日志,方便重试
最易被忽略的是字符编码:CSV 文件可能是 gbk 或 utf-8-sig,读取时漏掉 encoding 参数会导致乱码插入,后续查不到数据也看不出错在哪。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











