2017-05-01 15 views
0

COPYコマンドを使用してPostgres 9.6でUPSERT機能をon duplicate keyにすることはできますか?私はPostgresにインポートしているCSVファイルを持っていますが、重複したキー違反が含まれている可能性があります。したがって、COPYコマンドでエラーが発生し、それらに遭遇すると終了します。重複したキー違反で多数の行をPostgresにインポートする

ファイルが非常に大きいため、すべてのキーがメモリに収まらない可能性があるため、重複したキー違反につながる可能性のある行を処理するために、アプリケーションコードで前処理することができない場合があります。

重複したキー違反が含まれている可能性のある非常に多数の行をPostgresにインポートするにはどうすればよいですか?

+2

コピーがアップしていません。あなたは他のテーブルにコピーしてdiffereceを挿入することができます –

+0

@ VaoTsunどういう意味ですか?私はどのように '挿入差異'の部分を実装するか分からない。 – user779159

+0

しました。あなたの場合は英国ですから、 'left outer join ... where original.uk_att is null'から挿入する必要があります。異なる行(すべての列)を挿入する場合は、同様の方法で 'except'を使用してください。 –

答えて

1

拡張子file_fdwを使用すると、ファイルを開いてテーブルのようにクエリできます。

Read more in the documentation.

例:

create extension if not exists file_fdw; 

create server csv_server foreign data wrapper file_fdw; 

create foreign table my_csv_file (
    id integer, 
    should_be_unique_id integer, 
    some_other_columns text 
) server csv_server 
options (filename '/data/my_large_file.csv', format 'csv'); 

insert into my_new_table 
select distinct on (should_be_unique_id) * 
from my_csv_file 
order by should_be_unique_id, id desc; 

また、my_new_tableは、あなたが使用できる空でない場合

insert into my_new_table 
select * 
from my_csv_file 
on conflict ... update ... 
+0

使用方法の例を教えてください。 – user779159

1

サンプル:

t=# create table s90(i int primary key, t text); 
CREATE TABLE 
t=# insert into s90 select 1,'a'; 
INSERT 0 1 
t=# copy s90 from stdin delimiter ','; 
Enter data to be copied followed by a newline. 
End with a backslash and a period on a line by itself. 
>> 1,'b' 
>> 2,'c' 
>> \. 
ERROR: duplicate key value violates unique constraint "s90_pkey" 
DETAIL: Key (i)=(1) already exists. 
CONTEXT: COPY s90, line 1 

回避方法:

t=# create table s91 as select * from s90 where false;; 
SELECT 0 
t=# copy s91 from stdin delimiter ','; 
Enter data to be copied followed by a newline. 
End with a backslash and a period on a line by itself. 
>> 1,'b' 
>> 2,'c' 
>> \. 
COPY 2 
t=# with p as (select s91.* from s91 left outer join s90 on s90.i=s91.i where s90.i is null) 
insert into s90 select * from p; 
INSERT 0 1 
t=# select * from s90; 
i | t 
---+----- 
1 | a 
2 | 'c' 
(2 rows) 
関連する問題