2016-03-30 24 views
5

で発生した場合、私は、私はパフォーマンスが鍵となりますので、大量にこのテーブルに書き込む必要があるテーブルPostgresの - CONFLICT ON - UPDATEが代わりにINSERT

CREATE TABLE foo 
(
    f0 int, 
    time_stamp timestamp, 
    CONSTRAINT foo_pk PRIMARY KEY (f0) 
) 

を知っている方法を。ときどき、私はf0の既存の値を持つレコードを書き、今度はtime_stampを現在の時刻に更新するだけです。このため私はON CONFLICT..DO UPDATE節を使用します。

問題は、INSERTが発生したかどうか、またはUPDATEかどうかを知る必要があるということです。

ただし、第2のis_updateの列を使用しています。挿入するときは、私が欲しいものを得るためにRETURNING is_updateを使用するとfalse

`ON CONFLICT .. DO UPDATE set is_update=true` 

を挿入します。その問題は、データ自体に関連しない追加の列の導入です。

+0

[アップサートは、PostgreSQL 9.5以降UPSERTと更新したかどうかを確認するには?](HTTP: //stackoverflow.com/questions/34762732/how-to-find-out-if-an-upsert-was-an-update-with-postgresql-9-5-upsert) – lad2025

+0

@ lad2025この質問は以前に見つかりませんでしたが、ありがとう。しかし、提案された解決策は、私が試したことだが、この「UPSERT/ON CONFLICT」機能から抜けていると感じている機能のためにテーブルの追加の列があるために避けたいのです。 – Sagi

+0

[PostgreSQL Upsertは、システムカラムXMIN、XMAXなどを使用して挿入され更新された行を区別します](https://stackoverflow.com/q/39058213/1995738) – klin

答えて

0

fooテーブルでトリガー機能を作成できます。次に、insert操作をTG_OP予約語でトラップします。キーが存在する場合は更新し、そうでない場合は新しい行を挿入します。

CREATE OR REPLACE FUNCTION public.f0_update_on_duplicate() 
RETURNS trigger 
LANGUAGE plpgsql 
AS $function$ 
declare _exists boolean; 
begin 
    if TG_OP = 'INSERT' then 
    select exists(select true from foo where f0 = NEW.f0) into _exists; 
    raise notice '%', _exists; 
    if _exists = TRUE then 
     update foo set time_stamp = NEW.time_stamp where f0 = NEW.f0; 
     return NULL; 
    else 
     return NEW; 
    end if; 
    end if; 
end 
$function$; 

2.Attachテーブルをfooに手順:

CREATE TRIGGER update_on_duplicate 
BEFORE INSERT ON foo FOR EACH ROW EXECUTE PROCEDURE 
f0_update_on_duplicate(); 

3.Test挿入まだ巨大な行:)

1.Createで手順をテストしていません。これは、新しいTIME_STAMPとF0を更新する必要があります(assumming F0 = 5であるのfooテーブルに存在する):

INSERT INTO foo (f0, time_stamp) VALUES (5, now());