【问题标题】:Best way to bulk load CSV file into PostgreSQL table将 CSV 文件批量加载到 PostgreSQL 表中的最佳方法
【发布时间】:2020-07-09 03:31:51
【问题描述】:

我在D:\DataSet\business_names_202007/businessDataSet.csv 中有一个制表符分隔的 CSV 文件,其中包含 60 万条记录(可能会增加)。我想将整个数据加载到下面的 postgresql 表中。

PostgreSQL 表:

CSV 文件结构:

正如您在上面的结构中看到的,CSV 文件和数据库之间的列数不同(数据库中额外的“transform_business”列)。在加载数据时,我们还需要添加它,该列的值如下所示。

db中的“transform_business”列值与DataSet中的“BN_NAME”相同,有以下变化:转换为大写,单词之间的所有空格都应该删除

例如:

  • BN_NAME:墨尔本碰撞维修

  • transform_business: MELBOURNECOLLISIONREPAIR

  • 工具:Dbeaver

  • 数据库架构:testDev

  • 表名:testdevtable

Tutorial link

临时形成的copt语句:

COPY testdevtable(register_name,bn_name,bn_status,transform_business) 
FROM 'D:\DataSet\business_names_202007/businessDataSet.csv' DELIMITER E’\t’ CSV HEADER;

【问题讨论】:

    标签: postgresql csv command-line-interface dataloader


    【解决方案1】:

    如果它在我那里我会添加一个ON INSERT 触发器到业务表,它在INSERT 期间转换bn_name --> transform_business。然后将transform_business 排除在COPY 之外。第二种选择是在加载之前进行转换并将transform_business 和新数据添加到 CSV 文件中。

    将执行转换的示例 SQL 代码 sn-p:

    SELECT upper(replace('Melbourne Collision Repair Centre Mentone', ' ', ''));
                     upper                 
    ---------------------------------------
     MELBOURNECOLLISIONREPAIRCENTREMENTONE
    
    

    另一种选择是将COPY (register_name,bn_name,bn_status) 放入数据库中(表上没有触发器),然后运行:

    UPDATE business SET transform_business = upper(replace(bn_name, ' ', ''));
    
    

    不确定之后会发生什么,transform_business 值是否将与新数据一起输入。如果用户/应用程序不打算输入它,那么我认为您将回到运行 upper(replace(bn_name, ' ', '')) 的业务表上的触发器。

    【讨论】:

    • 嗨@Adrian,感谢您的回复。 CLI 中是否有任何选项可以通过单个尝试加载数据(加载其他表列以及“transform_business”的所需更改?
    • 嗨@Adrian,我们如何在加载前进行转换? bcoz 数据太长(最多 4000000)或请通过显示一些示例代码来详细说明?
    • 嗯,你将不得不在某个时候处理这​​个问题,只是你想在哪里付出代价的问题。用示例和另一个建议更新了答案。 COPY 处理数据的唯一选择是使用PROGRAM,这是您编写的用于将数据提供给COPY 的程序。我从来没有这样做过,所以我在那里帮不上什么忙。最好的办法是将基本数据存入数据库并在那里进行更改。
    【解决方案2】:

    也许您遗漏了一条有价值的信息:您运行的是哪个 Postgres 版本?如果您拥有或可以更新到版本 12,您可以重新定义您的表,以便将 transform_business 列作为生成的列。那么例如:

    create table table_name(
           id             bigint generated always as identity
         , register_name  text 
         , bn_name        text 
         , status         text 
         , transform_name text generated always as ( upper(replace(bn_name,' ',''))) stored
         ) ;
    

    如果您需要维护当前数据,那么您可以:

    alter table table_name  drop column transform_name; 
    alter table table_name  add transform_name text generated always as ( upper(replace(bn_name,' ',''))) stored; 
    

    这个选项会很慢,特别是如果表很大,但它是一次性过程。然后,任何一个选项都会给你一个“约束”,即 transform_name 不能直接更新,但会在 bn_name 更新时自动更新。

    然后您的复制命令将只加载 register_name、bn_name 和状态。

    【讨论】:

    • 嗨@Belayer,我正在使用11.5版本的postgreSQL,向DBA提出了将postgreSQL版本升级到12的问题。将检查并让你知道状态。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-09
    • 2021-01-06
    • 2018-07-22
    • 1970-01-01
    • 2017-08-20
    • 1970-01-01
    相关资源
    最近更新 更多