我需要从CSV文件导入名称和几何数据到PostgreSQL。individuals.csv
文件格式如下:
first_name,last_name,location
Russell,Wolff,{"type":"Feature","geometry":{"type":"Point","coordinates":[73.0786759127481,29.730356801638685]},"properties":{}}
CSV文件中的所有几何类型都是"type":"Point"
,并且该文件具有大约500K+记录。以上只是一个记录示例。
我创建了下面的表格来存储数据:
CREATE TABLE individuals (
id SERIAL PRIMARY KEY,
first_name VARCHAR(255),
last_name VARCHAR(255),
location_point GEOGRAPHY(Point, 4326) -- Use GEOGRAPHY data type for storing points
);
我写了下面的plpgsql
函数来做同样的事情:
CREATE OR REPLACE FUNCTION insert_csv_data(directory text) RETURNS void AS $$
DECLARE
file_name text;
csv_data json;
begin
-- Loop through GeoJSON files in the specified directory
FOR file_name IN
SELECT *
FROM pg_ls_dir(directory)
loop
IF file_name LIKE '%.csv' then
RAISE NOTICE 'GeoJSON data: %', pg_read_file('path/to/individuals.csv');
COPY individuals(first_name, last_name, location_point)
FROM 'path/to/individuals.csv'
CSV HEADER;
END IF;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
因此,我的想法是将directory
传递给包含多个CSV文件的函数,然后将每个文件中的数据COPY
传递给表个体。所以我在每个file_name
上运行一个循环。
当我运行这个函数时:SELECT public.insert_csv_data('path/to/directory');
我有一个RAISE NOTICE 'GeoJSON data: %', pg_read_file('path/to/individuals.csv');
是个人.csv文件的路径,它正确打印数据,如下所示:
GeoJSON data: first_name,last_name,location
Russell,Wolff,{"type":"Feature","geometry":{"type":"Point","coordinates":[73.0786759127481,29.730356801638685]},"properties":{}}
我得到一个错误:
SQL Error [22P04]: ERROR: extra data after last expected column
Where: COPY individuals, line 2: "Russell,Wolff,{"type":"Feature","geometry":{"type":"Point","coordinates":[73.0786759127481,29.730356..."
SQL statement "COPY individuals(first_name, last_name, location_point)
FROM 'path/to/individuals.csv'
CSV HEADER"
PL/pgSQL function insert_csv_data(text) line 15 at SQL statement
我的问题是:
1.现在我正在运行COPY命令,并将FROM作为1个文件的硬编码路径。如何动态地替换每个file_name的路径,例如COPY FROM中的directory || '/' || file_name
,以便从该文件复制数据,然后复制后续文件?
1.我需要从CSV中提取,
之后的geometry
键,然后将其插入location_point GEOGRAPHY(Point, 4326)
列。我怎么能做到呢?
我被困在这里,任何帮助都将不胜感激。谢谢你,谢谢
1条答案
按热度按时间uwopmtnx1#
现在我正在运行COPY命令,并将FROM作为1个文件的硬编码路径。如何动态地替换每个file_name的路径,例如COPY FROM中的
directory || '/' || file_name
,以便从该文件复制数据,然后复制后续文件?您可以在PL/pgSQL块中使用动态SQL:
将
text
变量直接传递给copy
命令是行不通的,调用text
返回函数(如concat()
或||
)也是行不通的。该命令需要一个文字,上面的动态SQL允许您首先执行函数,然后在将其作为文字传递之前评估保存其结果的变量。我需要从CSV中提取几何键,然后将其插入到列location_point GEOGRAPHY(Point,4326)中。我怎么能做到呢?
由于文件的结构,
copy
命令:相当于这样的
insert
语句:这将抛出一个错误;值比列多,因为
copy
默认为delimiter ','
。DELIMITER
指定在文件的每一行中分隔列的字符。**默认为文本格式的制表符,CSV
的逗号。**必须是单个单字节字符。除非使用正确的字符串引号,否则它会在找到逗号的地方分割输入行,因此在本例中,它会将最后一个字段分割为多个部分。要解决这个问题,您可以
1.通过一个接受
location
五部分的中间表运行数据,然后使用concat_ws(',',...)
重新组装它。使用quote '~'
(或文件中未使用的任何字符)覆盖默认的quote '"'
-否则copy
将解释并删除最后一列中的所有双引号"
:demo1如果您的
location_point
字段结构在整个文件中不是恒定的,则可能会中断。1.更稳健:用单引号将
location_point
字段括起来,并将quote $$'$$
或quote ''''
参数添加到copy
命令中。将;
上的逗号,
替换为,并添加delimiter ';'
参数:demo2替换可以用
sed
来完成,例如:模式末尾的
1
表示它将替换一行中的第一个逗号。在第一次替换之后,第二个逗号变成了第一个逗号,所以第二个模式也是针对第一个查找并替换它,但也用单引号包围所有内容,直到行尾。