2016-11-28 8 views
0

同じユニークな識別子を持つテーブルにいくつかの行を挿入しようとしていますが、他のフィールドはすべて異なります(行はマップ上のポイントを表し、同じ名前を持つようになります)。私が最後にしたいのは、問題の行を何らかの形で変更して、一意の識別子を持つようにすることです( "name0"、 "name1"、 "name2"などのように、挿入コマンド。重複した識別子を持つ行を挿入するうまい方法がありますか?

私は最近、Postgresの "ON CONFLICT"サポートが追加されていることを認識していますが、それは私が探しているものではありません。

Postgres 9.6 Documentationによると

CONFLICT句ONオプションは、ユニークな違反または排他制約違反エラーを上げるに代替アクションを指定します。挿入のために提案された個々の行ごとに、挿入が進むか、または代替conflict_actionが実行されます。 ... ON CONFLICT DO UPDATEは、挿入のために提案された行と競合する既存の行を、の代替アクションとして更新します。 ON競合機能がないように私は何をしたいことは1)問題のある行または挿入自体 2を変更するのいずれか)、代わりに更新でそれを置き換えるの(挿入を続行さ

)。これを達成するエレガントな方法はありますか?あるいは、私はもっと複雑なものを書く必要がありますか?

答えて

0

あなたはこれを行うことができます。シーケンスは、新しい行のPK列に固有のサフィックスを割り当てるために使用される

create table my_table 
( 
    name text primary key, 
    some_column varchar 
); 

create sequence my_table_seq; 

行動は次のように行うことができます「修正競合のインサートに挿入」:

with data (name, some_column) as (
    values ('foo', 'bar') 
), inserted as (
    insert into my_table 
    select * 
    from data 
    on conflict (name) do nothing 
    returning * 
) 
insert into my_table (name, some_column) 
select concat(name, '_', nextval('my_table_seq')), some_column 
from data 
where not exists (select 1 from inserted); 

あなたはPK列に値を挿入する最初の時間は、(CTE「挿入」内)の挿入がちょうど進行します。最後のinsertは何も挿入しません。where not exists()は、insertedが1行返されるためです。

これを2回目に実行すると、最初の挿入は何も挿入されないため、2番目(最終)の挿入が行われます。

「挿入された」CTEによって何かが挿入された場合、最終的な挿入がこの情報を「駆動する」ものであるため、総合ステートメントは影響を受ける「0 rows affected」を報告します。

関連する問題