web-dev-qa-db-fra.com

syntaxe pour MERGE / upsert sur une seule ligne dans SQL Server

J'essaie de faire une insertion/mise à jour d'une seule ligne sur une table, mais tous les exemples existent pour les ensembles.

Quelqu'un peut-il corriger ma syntaxe s'il vous plaît:

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

La résolution par marc_s est de convertir la ligne unique en une sous-requête - ce qui me fait penser que la commande MERGE n'est pas vraiment destinée aux upserts à une seule ligne.

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

Fondamentalement, vous êtes sur la bonne voie - mais il vous manque une source d'où vous souhaitez fusionner les données - essayez quelque chose comme ceci:

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

Il n'y a pas de syntaxe spéciale pour une seule ligne MERGE - tout ce que vous devez faire est d'utiliser une clause appropriée. Avec cette condition appropriée dans la clause ON, vous pouvez limiter la source à une seule ligne - pas de problème.

Et n'oubliez pas le point-virgule de fin! Pas de blague - c'est important!

Voir cet article de blog pour une très bonne introduction à MERGE.

46
marc_s

j'ai finalement obtenu la syntaxe Upsert en utilisant MERGE dans SQL Server 2008. En utilisant ce que Jacob voulait faire (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 syntaxe équivalente MERGE est:

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 (;).
102
Ian Boyd