2010-12-29 9 views
6

Więc idę z MySQL, gdzie mogę zrobić INSERT on DUPLICATE UPDATE:MERGE składnia używana do upsert lub wstawić na duplikat UPDATE

INSERT INTO table (a,b,c) 
VALUES (1,2,3) 
ON DUPLICATE KEY UPDATE c=c+1; 

Ale teraz używam PostgreSQL i są starania, aby dodać funkcjonalność upsert, wygląda na to, że MERGE może działać w tym, co chciałbym, ale chciał sprawdzić, czy jest to najbardziej optymalna składnia. Example Syntax 1, I've also seen this but don't understand how to implement. Nie próbowałem jeszcze tego, ponieważ myślałem, że MERGE został użyty do scalania danych z Table1 do Table2, czy coś takiego działa?

MERGE 
INTO table 
USING table 
ON  c = 1 
WHEN MATCHED THEN 
UPDATE 
SET  c=c+1 
WHEN NOT MATCHED THEN 
INSERT (a,b,c) 
VALUES (1,2,3) 

Jakieś inne sugestie?

Odpowiedz

13

Do MERGE jest dostępny, należy użyć tego solidne podejście: Insert, on duplicate update in PostgreSQL?

+0

w jakiej wersji Postgres jest to obsługiwane? –

+0

MERGE jest na Todo dla 9.1 http://wiki.postgresql.org/wiki/Todo –

+0

jest rubinowy klejnot dla tego: ['Upsert'] (https://github.com/seamusabshere/upsert) –

0
MERGE INTO table 
    USING (VALUES (1, 2, 3)) AS newvalues (a, b, c) 
    ON table.c = newvalues.c -- or whatever the PK is 
    WHEN MATCHED THEN UPDATE SET c = c + 1 
    WHEN NOT MATCHED THEN INSERT (a, b, c) 
           VALUES (newvalues.a, newvalues.b, newvalues.c) 

Kluczem tutaj jest to, że zamiast połączenia w innej tabeli utworzyć stałe źródło tabeli używając VALUES konstrukt w klauzuli USING. Dokładne zasady łączenia można oczywiście dostosować do gustu.

Zobacz także http://petereisentraut.blogspot.com/2010/05/merge-syntax.html.

+0

Ale to nie jest (jeszcze) obsługiwany przez PostgreSQL, prawda? –

+0

Hmm jest już to obsługiwane? –

+1

patch „czeka na autora” - https://commitfest.postgresql.org/action/commitfest_view/inprogress –

0

Myślę, że "MERGE" nie jest jeszcze w Postgres, ale ma być na 9.1.

Lubię używać RULE S zamiast

CREATE OR REPLACE RULE "insert_ignore" 
AS ON INSERT TO "table" WHERE 
    NEW.id = OLD.id --whatever your conditions are 
DO INSTEAD NOTHING; 

Co masz powiązany ("insert, na duplikatu aktualizacji (postgresql)") jest w zasadzie pewne pgsql że karmisz dane. Sądzę, że REGUŁA jest bardziej elegancka, ponieważ nie musisz wywoływać ich wyraźnie i działają one w tle bez potrzeby wywoływania procedury w obrębie rzeczywistego WSTAWU.

+0

Więc byłoby to INSERT inny ignorowanie/SKIP? –

+0

To IGNORE/SKIP, ponieważ sprawdzasz istnienie, a jeśli tak, pomiń to. To samo będzie działać dla AKTUALIZACJI działań. Rozważmy RULE jako "rodzaj wyzwalacza", który jest w stanie zmodyfikować samo zapytanie, przepisując je lub (jak w tym przypadku) ignorując części (lub wszystkie). – DrColossos

+1

Zrobiłem to, ale OLD.id dał błąd, nie podoba mi się wartość. jakieś pomysły? –

3

Do scalania jest obsługiwana najprostszym sposobem IMO jest po prostu podzielić go na dwa pytania:

BEGIN; 
    INSERT INTO t (a,b,c) VALUES (1,2,3) WHERE id != 1; 
    UPDATE t SET c=c+1 WHERE id = 1; 
END; 

gdzie id zostanie zmieniona na odpowiednim stanie.

+0

hmm Podobał mi się ten sposób, mimo że kosztuje cię dwa pytania: –

+0

hmm, nie działa w testach. daje mi błąd w warunku WHERE –