sql postgresql upsert postgresql-9.5

sql - Cómo hacer correctamente el upsert en postgres 9.5



postgresql postgresql-9.5 (2)

la sintaxis correcta de upsert con postgresql 9.5, debajo de la consulta muestra la column reference "gallery_id" is ambiguous error column reference "gallery_id" is ambiguous , ¿por qué?

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

Intenté cambiar WHERE gallery_id = $2; a WHERE category_gallery.gallery_id = $2; luego muestra el error, there is no unique or exclusion constraint matching the ON CONFLICT specification , pero no quiero configurar gallery_id o category_id como único porque quiero asegurarme de que ambas columnas son iguales y luego actualizar ...

¿Cómo hacer correctamente el upsert en postgres 9.5?

Si ON CONFLICT necesita una columna única, ¿debo usar otro método, cómo?



Quiero estar seguro de que tanto la columna múltiple como el conflicto actualicen, cuál es el uso correcto

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

tabla (category_id, gallery_id no es una columna única)

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


Como alternativa simplificada a la respuesta actualmente aceptada , la restricción UNIQUE se puede agregar de forma anónima al crear la tabla:

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

Entonces, la consulta de inserción se vuelve (similar a lo que ya se respondió):

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


La construcción ON CONFLICT requiere una restricción UNIQUE para funcionar. De la documentación en la cláusula INSERT .. ON CONFLICT :

La cláusula opcional ON CONFLICT especifica una acción alternativa para generar un error único de violación o restricción de exclusión . Para cada fila individual propuesta para la inserción, ya sea que se realice la inserción o, si se viola una restricción de árbitro o un índice especificado por conflict_target, se toma la acción de conflicto alternativa. ON CONFLICT DO NOTHING simplemente evita insertar una fila como acción alternativa. ON CONFLICT DO UPDATE actualiza la fila existente que entra en conflicto con la fila propuesta para la inserción como acción alternativa.

Ahora, la pregunta no es muy clara, pero probablemente necesite una restricción UNIQUE en las 2 columnas combinadas: (category_id, gallery_id) .

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

Si la fila que se va a insertar coincide con ambos valores con una fila ya en la tabla, en lugar de INSERT , haga una 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 ;

Puedes usar cualquiera de las columnas de la restricción UNIQUE:

ON CONFLICT (category_id, gallery_id)

o el nombre de la restricción:

ON CONFLICT ON CONSTRAINT category_gallery_uq