导入包含大量未知列名和数据类型的CSV文件(自动检测)
使用PostgreSQL 18,我想导入一个大型的 .csv 文件,其列名和数据类型未知。我有两个相关的 .csv 文件:
- 第一个文件大约包含100列,约2,000,000行数据,如姓名、地址、出生日期、电子邮件地址等,都是我县注册投票的选民的数据。体积接近1 GiB。我可以用Microsoft Access打开查看数据并进行查询。
- 第二个文件包含第一个文件中人员的完整投票历史记录。该文件大小为3.5 GiB。目前我还不知道它的列数,但预期会很多,因为这是投票历史,且可能跨越相当长的时间。
我想把数据导入PostgreSQL,并对其中的一些字段进行检索。我希望能够导入内容,并从两个源文件中自动生成列名,并将它们的数据关联起来。
PostgreSQL能否导入这一切,而不需要我手动创建一个包含所有列名的表?
我查看了 Can I automatically create a table in PostgreSQL from a csv file with headers?
但有提到 pgfutter 是一个被搁置的项目,这让我对它的可靠性产生了质疑。
我在考虑把SQLite作为中间步骤——这行得通吗?
步骤:
- 在命令提示符输入:
sqlite3 - 在sqlite3 CLI中输入:
.mode csv .import my_csv.csv my_table.output my_table_sql.sql.dump my_table- 最后在PostgreSQL中执行该SQL
解决方案
PostgreSQL能否导入这个,而不需要我手动创建一个包含所有列名的表?
CREATE EXTENSION pg_duckdb;
SELECT * FROM read_csv('my_csv.csv');
如果你愿意使用扩展,可以使用 pg_duckdb,它直接暴露了 DuckDB的 read_csv() 自动映射功能。标准的Postgres安装并不内置这样的功能。
你可以在他们的网站上了解它的工作原理 on their website:
DuckDB实现了一个 多假设CSV探测器,它能够自动检测方言、表头、日期/时间格式、列类型,并识别需要跳过的脏行。
你也可以通过一个独立的DuckDB 使用 postgres 扩展 来连接PostgreSQL。
INSTALL postgres;
LOAD postgres;
CREATE SECRET (
TYPE postgres, HOST '127.0.0.1', PORT 5432,
DATABASE postgres, USER 'postgres', PASSWORD 'yourpass'
);
ATTACH '' AS postgres_db (TYPE postgres);
在DuckDB内,CSV自动映射是内建功能,扩展还允许将结果直接保存到PostgreSQL。两者都使用 非常相似的SQL语法。
CREATE TABLE postgres_db.table_from_csv AS
SELECT * FROM 'my_csv.csv';
显式使用 read_csv() 可以 覆盖某些默认设置:
CREATE TABLE postgres_db.table_from_csv AS
SELECT * FROM read_csv('my_csv.csv', delim = '|', header = true);
手动方法也并不难:使用 bash head 检查前两行的表头、引号和分隔符。
head -n 2 my_csv.csv
并用它来构造你的 create table 命令,然后在尝试用 copy 加载内容之前执行。或者,将所有内容作为一个文本列一次性导入:
create table my_csv_raw(c text);
copy my_csv_raw from 'my_csv.csv' with (
format csv,
header false,
delimiter '鸡',
quote '鸡' );
管理员也可以用 pg_read_file() 来完成:
create table my_csv_raw(c) as
select * from pg_read_file('my_csv.csv');
然后,使用 string_to_array() 将其拆分,并使用 pg_input_is_valid() 测试从 text 到目标类型的转换。
备选方案
如果你愿意使用duckdb,这里有一个宏可以为csv(或gz)文件生成视图的DDL。
你可以很容易地改成一个表。
请检查所有数据类型,sniffer并不总是百分之百准确。
https://github.com/whelanmike/Open_Data_Analysis/blob/main/duckdb_create_view_from_csv_file.sql
