2016-04-22 12 views
12

sintassi corretta di upsert con postgresql 9.5, sotto query mostra l'errore column reference "gallery_id" is ambiguous, perché?Come fare correttamente upsert in postgres 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`; 

ho cercato il cambiamento WHERE gallery_id = $2;-WHERE category_gallery.gallery_id = $2; poi mostra errore there is no unique or exclusion constraint matching the ON CONFLICT specification, ma non voglio impostare gallery_id o category_id come unico becuase Voglio che entrambi colonna sono gli stessi, allora faccio aggiornamento ....

Come eseguire correttamente upsert in postgres 9.5?

se ON CONFLICT ha bisogno di una colonna univoca, dovrei usare un altro metodo, come?



voglio a sicuro a più colonne sia conflitto poi fare l'aggiornamento, che cosa è l'uso corretto

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`; 

tavolo (category_id, non gallery_id colonna unica)

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 | ... 

risposta

28

Il Il costrutto ON CONFLICT richiede un vincolo UNIQUE per funzionare. Dalla documentazione in INSERT .. ON CONFLICT clause:

Il ON CONFLICT clausola facoltativa specifica un'azione alternativa di sollevare una violazione unica o esclusione vincolo errore di violazione. Per ogni singola riga proposta per l'inserimento, o il ricavato dell'inserimento, o, se viene violato un vincolo di arbitro o un indice specificato da conflict_target, viene presa l'alternativa conflict_action. ON CONFLICT DO NOTHING semplicemente evita di inserire una riga come sua azione alternativa. ON CONFLICT DO UPDATE aggiorna la riga esistente che è in conflitto con la riga proposta per l'inserimento come sua azione alternativa.

Ora, la domanda non è molto chiaro, ma probabilmente avete bisogno di un vincolo UNIQUE sui 2 colonne combinati: (category_id, gallery_id).

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

Se da inserire la riga corrisponde entrambi valori con una fila già sul tavolo, allora invece di INSERT, do un 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 ; 

È possibile usare sia le colonne della vincolo UNIQUE:

ON CONFLICT (category_id, gallery_id) 

o il nome del vincolo:

ON CONFLICT ON CONSTRAINT category_gallery_uq 
+0

grazie per la risposta, ma non voglio category_id o gallery_id essere colonna unica, menzione in questione. Voglio che se category_id e gallery_id siano entrambi uguali, allora crea una nuova riga, per favore vedi il mio esempio di data di aggiornamento nella domanda – user1575921

+0

wow, grazie! Mi fraintendimento, lo proverò ora – user1575921

+0

sì se già esiste 'category_id = 1 e gallery_id = 3' quindi aggiorna, non inserisci. Io uso il tuo script, se voglio aggiornare 'category_id = 2 dove gallery_id = 3' non funziona. o dovrei aggiungere un altro script di aggiornamento? – user1575921

1

Come in alternativa semplificata al the currently accepted answer, il vincolo UNIQUE può essere anonima aggiunti al momento della creazione della tabella:

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

Quindi, l'interrogazione upsert diventa (simile a quello che è stato già risposto):

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