2016-04-22 11 views
12

korrekte Syntax von Upsert mit Postgresql 9.5, unter Abfrage zeigt column reference "gallery_id" is ambiguous Fehler, warum?Wie korrekt in Postgres upset 9.5

var dbQuery = `INSERT INTO category_gallery (
    category_id, gallery_id, create_date, create_by_user_id 
) VALUES ($1, $2, $3, $4) 
    ON CONFLICT (category_id) 
    DO UPDATE SET 
    category_id = $1, 
    last_modified_date = $3, 
    last_modified_by_user_id = $4 
    WHERE gallery_id = $2`; 

versuchte ich ändern WHERE gallery_id = $2;-WHERE category_gallery.gallery_id = $2; dann zeigt Fehler there is no unique or exclusion constraint matching the ON CONFLICT specification, aber Ich will nicht gallery_id oder category_id als einzigartige setzen weil ich sind Update gleiche beide Spalte sicher gehen wollen, dann tun ....

Wie richtig in Postgres 9.5 upsert?

wenn ON CONFLICT brauchen einzigartige Spalte, sollte ich andere Methode verwenden, wie?



möchte ich mehrere Spalte beide Konflikt dann aktualisiere sicher, was die korrekte Verwendung ist

var dbQuery = `INSERT INTO category_gallery (
    category_id, gallery_id, create_date, create_by_user_id 
) VALUES ($1, $2, $3, $4) 
    ON CONFLICT (category_id, gallery_id) 
    DO UPDATE SET 
    category_id = $1, 
    last_modified_date = $3, 
    last_modified_by_user_id = $4 
    WHERE gallery_id = $2`; 


var dbQuery = `INSERT INTO category_gallery (
    category_id, gallery_id, create_date, create_by_user_id 
) VALUES ($1, $2, $3, $4) 
    ON CONFLICT (category_id AND gallery_id) 
    DO UPDATE SET 
    category_id = $1, 
    last_modified_date = $3, 
    last_modified_by_user_id = $4 
    WHERE gallery_id = $2`; 

Tisch (category_id, gallery_id nicht eindeutige Spalte)

category_id | gallery_id | create_date | create_by_user_id | last_modified_date | last_modified_by_user_id 
1 | 1 | ... 
1 | 2 | ... 
2 | 2 | ... 
1 | 3 | ... 

Antwort

28

Die ON CONFLICT Konstrukt erfordert eine UNIQUE Einschränkung zu arbeiten. Aus der Dokumentation auf INSERT .. ON CONFLICT clause:

Die optionale ON CONFLICT-Klausel gibt eine alternative Aktion eine einmalige Verletzung oder Ausschlussbedingungs Verletzungsfehler zu erhöhen. Für jede einzelne Zeile, die für die Einfügung vorgeschlagen wird, wird entweder die Einfügung fortgesetzt oder, falls eine von constrict_target angegebene Arbitrierungseinschränkung oder ein Index verletzt wird, wird die alternative conflict_action verwendet. ON CONFLICT DO NOTHING vermeidet einfach das Einfügen einer Zeile als alternative Aktion. ON CONFLICT DO UPDATE aktualisiert die vorhandene Zeile, die mit der Zeile kollidiert, die zum Einfügen als alternative Aktion vorgeschlagen wird.

Nun ist die Frage nicht ganz klar, aber Sie müssen wahrscheinlich einen UNIQUE Druck auf den 2 Spalten kombiniert: (category_id, gallery_id).

ALTER TABLE category_gallery 
    ADD CONSTRAINT category_gallery_uq 
    UNIQUE (category_id, gallery_id) ; 

Wenn die Zeile eingefügt werden Spiele beide Werte mit einer Reihe bereits auf dem Tisch, dann statt INSERT, tun ein UPDATE:

INSERT INTO category_gallery (
    category_id, gallery_id, create_date, create_by_user_id 
) VALUES ($1, $2, $3, $4) 
    ON CONFLICT (category_id, gallery_id) 
    DO UPDATE SET 
    last_modified_date = EXCLUDED.create_date, 
    last_modified_by_user_id = EXCLUDED.create_by_user_id ; 

Sie können entweder die Spalten der Verwendung UNIQUE-Einschränkung:

ON CONFLICT (category_id, gallery_id) 

oder der Constraint-Name:

ON CONFLICT ON CONSTRAINT category_gallery_uq 
+0

danke für die antwort, aber ich möchte nicht category_id oder gallery_id eindeutig spalte sein, erwähnen in frage. Ich will sicher, wenn category_id und gallery_id beide gleich dann eine neue Zeile erstellen, siehe mein aktuelles Datum Beispiel in Frage – user1575921

+0

wow, danke! Ich missverstanden, ich werde es jetzt versuchen – user1575921

+0

ja wenn bereits existiert 'category_id = 1 und gallery_id = 3' dann update, nicht einfügen. Ich benutze dein Skript, wenn ich 'category_id = 2 wo gallery_id = 3' nicht funktioniert. oder sollte ich ein weiteres Update-Skript hinzufügen? – user1575921

1

Wie als vereinfachte Alternative zu the currently accepted answer, die UNIQUE Einschränkung anonym bei der Erstellung der Tabelle hinzugefügt werden können:

CREATE TABLE table_name (
    id TEXT PRIMARY KEY, 
    col TEXT, 
    UNIQUE (id, col) 
); 

Dann wird die Upsert Abfrage wird (ähnlich zu dem, was bereits beantwortet):

INSERT INTO table_name (id, col) VALUES ($1, $2) 
ON CONFLICT (id, col) 
    DO UPDATE SET col = $2;