2010-03-19 3 views
53

Sto provando a eseguire un inserimento/aggiornamento di riga singola su un tavolo ma tutti gli esempi disponibili sono per gli insiemi.per riga singola MERGE/upsert in SQL Server

Chiunque può risolvere la mia sintassi per favore:

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') 

Risoluzione per marc_s è quello di convertire la singola riga di una sottointerrogazione - che mi fa pensare il comando merge non è realmente inteso per singolo upserts fila.

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 , le linee sono spaziate così vicine nel mio browser che alcuni dei caratteri di sottolineatura non vengono visualizzati. – Jacob

risposta

42

In sostanza, sei sulla strada giusta - ma ti manca una fonte da cui si desidera unire i dati - provare qualcosa di simile:

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') 
; 

Non c'è una sintassi speciale per una singola riga MERGE - tutto ciò che devi fare è usare una clausola appropriata. Con la condizione corretta nella clausola ON, è possibile limitare l'origine a una singola riga, nessun problema.

E non dimenticare il punto e virgola finale! Non è uno scherzo, è importante!

Vedere this blog post per un'introduzione davvero buona a MERGE.

+6

Non ho un altro menu. Stai dicendo che devo simularne uno con qualcosa di simile? UTILIZZO (SELEZIONA 0 mt_member, 110 mt_topic) come sorgente – Jacob

+0

@Jacob: devi avere una fonte, si - una subquery come hai detto dovrebbe andare bene - prova! –

+5

Per chiunque sia confuso da questa risposta, controlla [questa altra domanda] (http://stackoverflow.com/questions/11216067/what-is-using-in-sql-server-2008-merge-syntax). –

88

ho finalmente avuto la sintassi upsert utilizzando MERGE in SQL Server 2008. Utilizzando quello che Jacob voleva da fare (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 

L'equivalente MERGE sintassi è:

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

Nella clausola 'WHEN NOT MATCHED THEN', perché inserisci' VALUES (mt_member, mt_topic, mt_notes) 'e non' VALUES (foo.mt_member, foo.mt_topic, foo.mt_notes) '? –

+0

@ SamP Perché, perché no? È come se SQL Server ottenga i valori da qualche posto * diverso * rispetto alla pseudo-tabella 'pippo'? Oh, aspetta ... –

+0

Non la riga "UPDATE member_topic SET mt_notes = 'test'" nell'esempio non-merge aggiorna tutte le righe nella tabella? Non è ciò che era inteso. –