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 语句存在于两个突变 - 服务器端 COPYpsql\copy。这两个语句具有相同的语法和非常相似的行为。存在显着差异 - \copy 正在使用客户端文件系统。 COPY 正在使用服务器端文件系统。 psql \copy 不应被称为服务器端 SQL 命令。它直接从psql 或一些bash 脚本中使用。

服务器端COPY 用于海量导出/导入操作。当它使用文件系统时,它只能由具有超级用户权限的用户使用。非特权用户必须使用stdinstdout 目标,但应用程序必须支持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 操作系统中工作的,因此使用 psqlstdinstdout 的示例是无关紧要的。【参考方案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 命令将数据加载到数据库中。这实际上是 \copypsql 工作时所做的。

【讨论】:

单个 INSERTS 将比 COPY 慢得多。通常它取决于大小,但对于大量进口,这不是一个好建议。 @PavelStehule 这是非常正确的,但不是问题的解决方案。而且我没有在 OP 中读到任何暗示这可能是一个巨大的 csv 文件的内容。 我不同意“这实际上是 \copy 在 psql 中工作时所做的事情”这句话 - 当然这取决于细节 - 但它有点令人困惑 COPY 也支持插入表格。检查 COPY table_name FROM 'filename'

以上是关于PostgreSQL - \copy 命令的主要内容,如果未能解决你的问题,请参考以下文章

使用 PostgreSQL 时使用 COPY 命令处理错误

Django:RunSQL:使用 PostgreSQL COPY 命令

PostgreSQL COPY 命令中动态生成的表名

在 PostgreSQL 中使用 COPY FROM 命令在多个表中插入

COPY命令在字符串值中使用逗号 - Postgresql 10

postgresql数据库 copy命令导入表不成功