PostgreSQL - \copy 命令
Posted
技术标签:
【中文标题】PostgreSQL - \\copy 命令【英文标题】:PostgreSQL - \copy commandPostgreSQL - \copy 命令 【发布时间】:2015-05-27 02:31:26 【问题描述】:我尝试了上面的代码。我设法编译。但是,当我运行时,它给了我错误:
Exception in thread "main" org.postgresql.util.PSQLException: ERROR: syntax error at or near "\"
Position: 1
显示我运行的查询是错误的:
String query ="\\COPY tmp from 'E:\\load.csv' delimiter ',';";
查询的System.out.println
是:
query string: \COPY tmp from 'E:\load.csv' delimiter ',';
我在 PostgresSQL 客户端中运行查询:\COPY tmp from 'E:\load.csv' delimiter ',';
,它可以工作。
发生了什么?
Class.forName (driver);
conn = DriverManager.getConnection(host+dbname,user,password);
stmt = (java.sql.Statement) conn.createStatement();
//
PreparedStatement prepareUpdater = null;
conn.setAutoCommit(false);
String query ="\\COPY tmp from 'E:\\load.csv' delimiter ',';";
System.out.print("query string: "+query);
System.out.println("Query:"+query);
prepareUpdater = conn.prepareStatement(query);
prepareUpdater.executeUpdate();
prepareUpdater.close();
【问题讨论】:
命令是COPY,没有反斜杠 我需要运行的实际命令是 \COPY 如果我只放 COPY,我可以将 .csv 文件加载到表中 - 错误必须是超级用户 \COPY 是 psql 内部命令,不是 SQL 命令。只有 psql 能理解。 【参考方案1】:PostgreSQL COPY
语句存在于两个突变 - 服务器端 COPY
和 psql
端 \copy
。这两个语句具有相同的语法和非常相似的行为。存在显着差异 - \copy
正在使用客户端文件系统。 COPY
正在使用服务器端文件系统。 psql
\copy
不应被称为服务器端 SQL 命令。它直接从psql
或一些bash
脚本中使用。
服务器端COPY
用于海量导出/导入操作。当它使用文件系统时,它只能由具有超级用户权限的用户使用。非特权用户必须使用stdin
、stdout
目标,但应用程序必须支持COPY API。
psql
支持它-因此您可以使用它来将某个表从一个表复制到另一个表:
psql -c "COPY mytab TO stdout" db1 | psql -c "COPY targettab FROM stdin" db2
对于 Java 环境,您必须使用一些支持,例如 CopyManager。见how to copy a data from file to PostgreSQL using JDBC?
COPY
语句的导入速度比INSERT
语句的导入速度要快得多 - 但依赖于一些额外的开销 - 在没有大量索引且没有慢触发器的普通表上差异会很大。如果表上有很多索引或较慢的触发器,那么 COPY
的加速将是微不足道的。
【讨论】:
OP 显然是关于在带有 Java 的 Windows 操作系统中工作的,因此使用psql
与 stdin
和 stdout
的示例是无关紧要的。【参考方案2】:
感谢您的反馈。
我设法使用 CSVReader 加载 *.csv。
我下载了 CSVReader 包并将其包含在我的代码中。
它工作正常。
CsvReader products = new CsvReader("/tmp/ip2location/IP-COUNTRY-REGION-CITY-LATITUDE-LONGITUDE-ISP-DOMAIN-MOBILE-USAGETYPE.CSV");
products.readHeaders();
while (products.readRecord())
String ip_from = products.get("ip_from"); //int
String ip_to = products.get("ip_to"); //int
PreparedStatement prepareStat = null;
String sqlIinsert = "insert into ip2location_tmp(ip_from, ip_to )"
+ " VALUES ("+ip_from+","+ip_to+");";
System.out.println("sqlInsert:"+sqlIinsert);
prepareStat = conn.prepareStatement(sqlIinsert);
prepareStat.executeUpdate();
products.close();
enter code here
【讨论】:
您对PreparedStatement
的使用完全错误(而且效率低下)。您应该只在使用占位符的 while 循环之前准备它一次。然后在循环内部使用setString()
提供实际值,然后再调用executeUpdate()
。【参考方案3】:
您使用COPY
而不是/COPY
String query ="COPY tmp from 'E://load.csv' delimiter ','";
会有用的
【讨论】:
【参考方案4】:COPY
SQL 命令从本地文件系统读取文件,服务器进程必须有权访问它。
\copy
命令是psql
指令,仅在该环境中可用。您不能在 SQL 查询中使用它。
由于 Java 有一个很好的 CSV 阅读器类,您可以简单地在代码中读取文件,然后使用单独的 INSERT
命令将数据加载到数据库中。这实际上是 \copy
在 psql
工作时所做的。
【讨论】:
单个 INSERTS 将比 COPY 慢得多。通常它取决于大小,但对于大量进口,这不是一个好建议。 @PavelStehule 这是非常正确的,但不是问题的解决方案。而且我没有在 OP 中读到任何暗示这可能是一个巨大的 csv 文件的内容。 我不同意“这实际上是 \copy 在 psql 中工作时所做的事情”这句话 - 当然这取决于细节 - 但它有点令人困惑 COPY 也支持插入表格。检查 COPY table_name FROM 'filename'以上是关于PostgreSQL - \copy 命令的主要内容,如果未能解决你的问题,请参考以下文章
Django:RunSQL:使用 PostgreSQL COPY 命令
在 PostgreSQL 中使用 COPY FROM 命令在多个表中插入