2016-03-30 11 views
5

Ich habe eine TabellePostgres - KONFLIKT - Wie kann man wissen, ob ein Update statt einer INSERT aufgetreten

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

Ich muss diese Tabelle in großen Mengen schreiben, so dass Leistung ist der Schlüssel. Manchmal schreibe ich einen Datensatz mit einem vorhandenen Wert für f0 und aktualisiere nur den time_stamp auf die aktuelle Zeit. Dazu verwende ich eine ON CONFLICT..DO UPDATE Klausel.

Das Problem ist, dass ich wissen muss, ob eine INSERT aufgetreten ist oder eine UPDATE.

Ich obwohl auf eine zweite is_update Spalte verwenden. Beim Einfügen einfügen false und

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

Dann RETURNING is_update verwenden zu bekommen, was ich will. Das Problem dabei ist die Einführung einer zusätzlichen Spalte, die nicht mit den Daten selbst zusammenhängt.

+0

[Wie um herauszufinden, ob ein Upsert ein Update mit PostgreSQL 9.5+ UPSERT war?] (Http: //stackoverflow.com/questions/34762732/how-to-find-out-if-an-upsert-was-an-update-with-postgresql-9-5-upsert) – lad2025

+0

@ lad2025 Diese Frage konnte ich nicht finden, Vielen Dank. Die vorgeschlagene Lösung ist jedoch, was ich gesagt habe, dass ich versucht habe, aber wegen der zusätzlichen Spalte in meiner Tabelle für einige Funktionalität vermeiden möchte, die ich von dieser "UPSERT/ON CONFLICT" -Funktion vermisse. – Sagi

+0

[PostgreSQL Upsert unterscheidet zwischen eingefügten und aktualisierten Zeilen mithilfe der Systemspalten XMIN, XMAX und anderen] (https://stackoverflow.com/q/39058213/1995738) – klin

Antwort

0

Sie können Trigger-Funktion auf Foo-Tabelle erstellen. Dann fangen Sie die insert Operation mit reserviertem TG_OP-Wort, wenn Schlüssel vorhanden ist, aktualisieren Sie, andernfalls fügen Sie eine neue Zeile ein. Noch nicht mit riesigen Reihen getestet :)

1.Erstellen das Verfahren:

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.Stecken die Prozedur Tabellen foo:

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

3.Test Einsatz. Dies sollte f0 mit neuen time_stamp aktualisieren (assumming f0 = 5 ist vorhanden in foo Tabellen):

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