PostgreSQL使用COPY导入CSV提示No such file or directory如何解决?
问题产生原因
你遇到的找不到文件问题是由systemd服务的PrivateTmp机制导致的:
Manjaro这类Arch系发行版默认给PostgreSQL的systemd服务配置了PrivateTmp=true参数,该参数会为PostgreSQL服务进程创建独立的/tmp私有命名空间:
- 你在用户层看到的
/tmp/test.csv属于系统全局的/tmp目录 - PostgreSQL服务进程访问的
/tmp是专属隔离目录,和全局/tmp完全不互通,所以即便文件权限正常,服务也找不到你放入全局/tmp的文件
解决方案
方案1:使用psql客户端的\copy命令(最推荐,无需修改系统配置)
原生COPY是服务端命令,需要服务端进程能直接访问文件;而\copy是psql的客户端命令,会读取客户端本地文件后传给服务端,完全绕开服务端文件权限和PrivateTmp的限制,也不需要超级用户权限。
注意\copy是客户端命令,无法在服务端运行的存储过程中执行,直接在psql命令行执行即可:
-- 先手动创建临时表 create table temporaryData( courseSectionID varchar(10), instructorID varchar(25), courseTitle varchar(50) ); -- 用\copy导入,路径填你本地客户端的csv文件实际路径即可 \copy temporaryData from '/home/milad/Desktop/myFolder/csvFiles/test.csv' delimiter ',' csv; -- 处理完数据后删除临时表即可 drop table temporaryData;
如果你用DBeaver这类可视化工具,也可以直接用工具自带的CSV导入功能,本质也是客户端导入逻辑,不会有服务端文件访问问题。
如果你必须在存储过程中执行导入逻辑,可选择下面两个方案:
方案2:修改PostgreSQL的systemd配置关闭PrivateTmp
- 执行命令编辑PostgreSQL的systemd服务覆盖配置:
sudo systemctl edit postgresql.service
- 在打开的编辑窗口输入以下内容:
[Service] PrivateTmp=false
- 保存退出后重载配置并重启PostgreSQL服务:
sudo systemctl daemon-reload sudo systemctl restart postgresql.service
修改完成后,PostgreSQL就能正常访问全局/tmp目录下的文件。
方案3:将CSV放入PostgreSQL服务的数据目录
你也可以把CSV文件放到PostgreSQL的专属数据目录(通常为/var/lib/postgres/下对应版本的子目录),给postgres用户分配文件的读取权限,即可正常使用COPY命令读取。
内容的提问来源于stack exchange,提问作者milad
相关产品推荐
相关产品推荐

