2010-03-19 29 views
53

Estoy tratando de hacer una inserción/actualización de una sola fila en una tabla, pero todos los ejemplos que hay son para conjuntos.sintaxis para fila única MERGE/upsert en SQL Server

¿Alguien puede arreglar mi sintaxis favor:

MERGE member_topic ON mt_member = 0 AND mt_topic = 110 
WHEN MATCHED THEN UPDATE SET mt_notes = 'test' 
WHEN NOT MATCHED THEN INSERT (mt_member, mt_topic, mt_notes) VALUES (0, 110, 'test') 

Resolución por marc_s es convertir la hilera a una sub consulta - que me hace pensar el comando MERGE no está realmente destinado a upserts de una sola hilera.

MERGE member_topic 
USING (SELECT 0 mt_member, 110 mt_topic) as source 
ON member_topic.mt_member = source.mt_member AND member_topic.mt_topic = source.mt_topic 
WHEN MATCHED THEN UPDATE SET mt_notes = 'test' 
WHEN NOT MATCHED THEN INSERT (mt_member, mt_topic, mt_notes) VALUES (0, 110, 'test'); 
+0

Hmm , las líneas están espaciadas tan cerca en mi navegador que algunos de los guiones bajos no se muestran. – Jacob

Respuesta

42

Básicamente, estás en el camino correcto - pero que se está perdiendo una fuente desde la que desea combinar los datos - intentar algo como esto:

MERGE 
    member_topic AS target 
USING 
    someOtherTable AS source 
ON 
    target.mt_member = source.mt_member 
    AND source.mt_member = 0 
    AND source.mt_topic = 110 
WHEN MATCHED THEN 
    UPDATE SET mt_notes = 'test' 
WHEN NOT MATCHED THEN 
    INSERT (mt_member, mt_topic, mt_notes) VALUES (0, 110, 'test') 
; 

No hay ninguna sintaxis especial para una sola fila MERGE: todo lo que necesita hacer es usar una cláusula adecuada. Con esa condición adecuada en la cláusula ON, puede limitar el origen a una sola fila, no hay problema.

¡Y no olvides el punto y coma final! No es broma, ¡es importante!

Ver this blog post para una muy buena introducción a MERGE.

+6

No tengo ninguna otra. ¿Estás diciendo que tengo que simular uno con algo como esto? UTILIZANDO (SELECCIONE 0 mt_member, 110 mt_topic) como fuente – Jacob

+0

@Jacob: tiene que tener una fuente, sí, una subconsulta como la que menciona debería estar bien, ¡pruébelo! –

+5

Para cualquier persona confundida por esta respuesta, consulte [esta otra pregunta] (http://stackoverflow.com/questions/11216067/what-is-using-in-sql-server-2008-merge-syntax). –

88

que finalmente me dieron la sintaxis Upsert usando MERGE en SQL Server 2008. Utilizando lo que Jacob quería hacer (un Upsert):

IF EXISTS(SELECT * FROM member_topic WHERE mt_member = 0 AND mt_topic = 110) 
BEGIN 
    --update existing row 
    UPDATE member_topic SET mt_notes = 'test' 
    WHERE mt_member = 0 
    AND mt_topic = 110 
END 
ELSE 
BEGIN 
    --insert new row 
    INSERT INTO member_topic (mt_member, mt_topic, mt_notes) 
    VALUES (0, 110, 'test') 
END 

La sintaxis es equivalente MERGE:

MERGE member_topic 
USING ( 
    VALUES (0, 110, 'test') 
) AS foo (mt_member, mt_topic, mt_notes) 
ON member_topic.mt_member = foo.mt_member 
    AND member_topic.mt_topic = foo.mt_topic 
WHEN MATCHED THEN 
    UPDATE SET mt_notes = foo.mt_notes 
WHEN NOT MATCHED THEN 
    INSERT (mt_member, mt_topic, mt_notes) 
    VALUES (foo.mt_member, foo.mt_topic, foo.mt_notes) 
; --A MERGE statement must be terminated by a semi-colon (;). 
+8

En la cláusula 'WHEN NOT MATCHED THEN', ¿por qué inserta' VALUES (mt_member, mt_topic, mt_notes) 'y no' VALUES (foo.mt_member, foo.mt_topic, foo.mt_notes) '? –

+0

@SamP ¿Por qué no? ¿Es como que el Servidor SQL va a obtener los valores de un lugar * otro * que el pseudo-tabla 'foo'? Oh, espera ... –

+0

¿La línea "UPDATE member_topic SET mt_notes = 'test'" no se fusionará en la actualización de ejemplo _all_ rows en la tabla? No fue lo que se pretendía. –

Cuestiones relacionadas