【问题标题】:How to COPY to multiple CSV files in PostgreSQL?如何在 PostgreSQL 中复制到多个 CSV 文件?
【发布时间】:2017-04-08 14:39:16
【问题描述】:

我在 Postgres 中有一个 PostGIS 点数据库,我想将几​​个地理上不同区域的点提取到 CSV 文件中,每个区域一个文件。

我已经设置了一个带有区域多边形和区域标题的 area 表,我想有效地循环通过该表,使用 Postgis 之类的 st_intersects() 来选择要放入每个 CSV 文件的数据,并且从面积表的标题中获取 CSV 文件的文件名。

我对执行交集代码和设置 CSV 输出的细节感到满意 - 我不知道如何为每个区域执行此操作。是否可以通过某种加入来做这样的事情?还是我需要使用存储过程来完成,并在 plpgsql 中使用循环构造?

【问题讨论】:

  • 实际的表定义和您的 Postgres 版本将有助于使问题变得清晰。

标签: postgresql csv postgis plpgsql postgresql-copy


【解决方案1】:

您可以在 plpgsql 中遍历 area 表中的行。但请注意正确引用标识符和值:

假设这个设置:

CREATE TABLE area (
  title text PRIMARY KEY
, area_polygon geometry
); 

CREATE TABLE points(
  point_id serial PRIMARY KEY
, the_geom geometry);

你可以使用这个 plpgsql 块:

DO
$do$
DECLARE
   _title text;
BEGIN
   FOR _title IN
      SELECT title FROM area
   LOOP
      EXECUTE format('COPY (SELECT p.*
                            FROM   area   a
                            JOIN   points p ON ST_INTERSECTS(p.the_geom, a.area_polygon)
                            WHERE  a.title = %L) TO %L (FORMAT csv)'
                   , _title
                   , '/path/to/' || _title || '.csv');
   END LOOP;
END
$do$;

使用带有 %L 的格式(对于字符串 literal)来获得正确引用的字符串,以避免语法错误和可能的 SQL 注入。您仍然需要在 area.title 中使用适用于文件名的字符串。)

还要小心地引用文件名作为一个整体,而不仅仅是它的标题部分。

您必须将整个命令连接为字符串。 “实用命令”COPY 不允许变量替换。这只有通过核心 DML 命令 SELECTINSERTUPDATEDELETE 才能实现。见:

所以不要在循环中读出area.area_polygon。必须将其转换为 text 才能将其连接到查询字符串中,其中文本表示将被转换回 geometry (或任何您实际未公开的数据类型)。这很容易出错。

相反,我只阅读area.title 来唯一标识行并在内部处理查询中的其余部分。

【讨论】:

    【解决方案2】:

    您可以使用 plpgsql 函数或内联 do(如果您只需要执行一次并且不想存储函数。)

    do $body$
      DECLARE i int;
      BEGIN FOR i IN SELECT DISTINCT city FROM table
        LOOP RAISE
          NOTICE 'foo';
          EXECUTE format($$COPY (SELECT * FROM foo WHERE x='%s') TO /tmp/%s$$, i, i); 
        END LOOP;
        RETURN;
      END;
    $body$ LANGUAGE plpgsql;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-17
      • 2013-07-13
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 2013-09-03
      • 2019-11-08
      • 1970-01-01
      相关资源
      最近更新 更多