如何在 PostgreSQL 中复制到多个 CSV 文件?
How to COPY to multiple CSV files in PostgreSQL?
我在 Postgres 中有一个 PostGIS 点数据库,我想将几个不同地理区域的点提取到 CSV 文件中,每个区域一个文件。
我已经设置了一个带有区域多边形和区域标题的 area
table,我想有效地循环遍历 table,使用类似 Postgis 的 [=11] =] 到 select 每个 CSV 文件中的数据,并从 table.
区域的标题中获取 CSV 文件的文件名
我很满意table 执行交集代码和设置 CSV 输出的详细信息 - 我不知道如何为每个区域执行此操作。是否可以通过某种连接来做这样的事情?或者我是否需要使用存储过程来完成,并在 plpgsql 中使用循环构造?
您可以使用 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;
您可以在 plpgsql 中遍历 area
table 中的行。但要注意正确引用标识符和值:
假设此设置:
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 命令 SELECT
、INSERT
、UPDATE
和 DELETE
才有可能做到这一点。参见:
所以不要在循环中读出area.area_polygon
。它必须转换为 text
才能将其连接到查询字符串中,其中文本表示将转换回 geometry
(或任何您实际未公开的数据类型)。这很容易出错。
相反,我只阅读 area.title
以唯一标识该行并在内部处理查询中的其余部分。
我在 Postgres 中有一个 PostGIS 点数据库,我想将几个不同地理区域的点提取到 CSV 文件中,每个区域一个文件。
我已经设置了一个带有区域多边形和区域标题的 area
table,我想有效地循环遍历 table,使用类似 Postgis 的 [=11] =] 到 select 每个 CSV 文件中的数据,并从 table.
我很满意table 执行交集代码和设置 CSV 输出的详细信息 - 我不知道如何为每个区域执行此操作。是否可以通过某种连接来做这样的事情?或者我是否需要使用存储过程来完成,并在 plpgsql 中使用循环构造?
您可以使用 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;
您可以在 plpgsql 中遍历 area
table 中的行。但要注意正确引用标识符和值:
假设此设置:
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 命令 SELECT
、INSERT
、UPDATE
和 DELETE
才有可能做到这一点。参见:
所以不要在循环中读出area.area_polygon
。它必须转换为 text
才能将其连接到查询字符串中,其中文本表示将转换回 geometry
(或任何您实际未公开的数据类型)。这很容易出错。
相反,我只阅读 area.title
以唯一标识该行并在内部处理查询中的其余部分。