2016-12-26 18 views
4

我有一个30 GB的制表符分隔文本文件,其中有超过1亿行,当我想使用\ copy命令将此文本文件导入到PostgreSQL表中时,有些行会导致错误。如何忽略这些行,并在导入到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)); 
+0

确定。标志缩回。 – MYGz

+1

[如何用psql \ copy元命令忽略错误]的可能重复(http://stackoverflow.com/questions/36634360/how-to-ignore-errors-with-psql-copy-meta-command) – dmfay

+0

@ dmfay很难在导入之前编辑文本文件,因为很多不同的行有不同的问题。如果存在一种方法在导入之前逐一检查行,然后针对各行运行\ copy命令,这将会有所帮助。 –

回答

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

+0

如何将数据从我的11列选项卡分隔的文本文件导入单个列表? –

+0

使用文本文件中不存在的字符作为分隔符 –

+1

这是一个由多种语言组成的30 GB文本文件。任何角色都可以存在。是不是有一个更准确的方式从11列文件导入到1列表? –

0

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

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

0

创建一个表您可以使用BEFORE INSERT - 触发器并检查您的标准。如果记录未通过检查,请将日志(或单独的表中的条目)写入并返回null。如果可能和可行的话,你甚至可以纠正一些值。

当然,如果检查标准需要其他查询(如查找重复键等),则可能会出现性能问题。但我不知道是哪一种“在不同行不同的问题:”你的意思是......

赋予还StackExchange Database Administrators答案,并从Bartosz Dmytrak at PostgreSQL forum采取了以下例子:

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"(); 
相关问题