如何从PostgreSQL中的制表符分隔文本文件导入时忽略某些行?

时间:2016-12-26 14:12:30

标签: sql postgresql text

我有一个30 GB的制表符分隔文本文件,其行数超过1亿,当我想使用\ copy命令将此文本文件导入PostgreSQL表时,某些行会导致错误。如何在导入到postgresql时忽略这些行并记录被忽略的行?

我通过SSH连接到我的机器,所以我不能使用pgadmin!

在导入之前编辑文本文件非常困难,因为很多不同的行都有不同的问题。如果在导入之前有一种方法可以逐行检查行,然后对各行运行\ copy命令,那将会很有帮助。

以下是生成表格的代码:

CREATE TABLE Papers(
    Paper_ID CHARACTER(8) PRIMARY KEY,
    Original_paper_title TEXT,
    Normalized_paper_title TEXT,
    Paper_publish_year INTEGER, 
    Paper_publish_date DATE,
    Paper_Document_Object_Identifier TEXT,
    Original_venue_name TEXT,
    Normalized_venue_name TEXT,
    Journal_ID_mapped_to_venue_name CHARACTER(8),
    Conference_ID_mapped_to_venue_name CHARACTER(8),
    Paper_rank BIGINT,
    FOREIGN KEY(Journal_ID_mapped_to_venue_name) REFERENCES Journals(Journal_ID),
    FOREIGN KEY(Conference_ID_mapped_to_venue_name) REFERENCES Conferences(Conference_ID));

4 个答案:

答案 0 :(得分:3)

不要直接加载到目标表,而是加载到单个列临时表。

create table Papers_stg (rec text);

加载完所有数据后,您可以使用SQL对数据进行验证。

查找字段数错误的记录:

select  rec
from    Papers_stg
where   cardinality(string_to_array(rec,'       ')) <> 11

创建一个包含所有文本字段的表

create table Papers_fields_text
as
select  fields[1]  as Paper_ID                          
       ,fields[2]  as Original_paper_title              
       ,fields[3]  as Normalized_paper_title            
       ,fields[4]  as Paper_publish_year                
       ,fields[5]  as Paper_publish_date                
       ,fields[6]  as Paper_Document_Object_Identifier  
       ,fields[7]  as Original_venue_name               
       ,fields[8]  as Normalized_venue_name             
       ,fields[9]  as Journal_ID_mapped_to_venue_name   
       ,fields[10] as Conference_ID_mapped_to_venue_name
       ,fields[11] as Paper_rank                        

from   (select  string_to_array(rec,'       ')  as fields
        from    Papers_stg
        ) t
where   cardinality(fields) = 11

对于字段转换检查,您可能希望使用描述为here

的概念

答案 1 :(得分:0)

您唯一的选择是使用逐行处理。编写shell脚本(例如),它将循环通过输入文件并将每行发送到“copy”然后检查执行结果,然后将失败的行写入某些“err_input.txt”。

更复杂的逻辑可以提高处理速度。使用“部分”而不是逐行,并在失败的段上使用逐行逻辑。

答案 2 :(得分:0)

答案 3 :(得分:0)

您可以使用null - 触发器并检查您的条件。如果记录未通过检查,请将日志(或条目写入单独的表)并返回CREATE OR REPLACE FUNCTION "myschema"."checkTriggerFunction" () RETURNS TRIGGER AS $BODY$ BEGIN IF EXISTS (SELECT 1 FROM "myschema".mytable WHERE "MyKey" = NEW."MyKey") THEN RETURN NULL; ELSE RETURN NEW; END IF; END; $BODY$ LANGUAGE plpgsql; and trigger: CREATE TRIGGER "checkTrigger" BEFORE INSERT ON "myschema".mytable FOR EACH ROW EXECUTE PROCEDURE "myschema"."checkTriggerFunction"(); 。如果可能且可行,您甚至可以更正某些值。

当然,如果检查条件需要其他查询(例如查找重复的密钥等),则可能会出现性能问题。但我不确定不同行中的哪种&#34;不同的问题&#34;你的意思是......

还在StackExchange Database Administrators上给出答案,以下示例来自Bartosz Dmytrak at PostgreSQL forum

{{1}}