SQL : l’instruction MERGE

Je vais aujourd’hui vous faire partager un sujet qui est dans ma to-do list depuis plusieurs mois et dont je me sers très souvent : l’instruction MERGE en SQL.

Cette instruction est apparue avec SQL Server 2008 et permet de combiner plusieurs opérations DML (Data Modification Language -> INSERT, UPDATE, DELETE) en une seule instruction. Elle est très pratique pour synchroniser 2 tables entre elles. Voici les principaux éléments à mettre en place, que je vais appliquer à un exemple :

  • Une source contenant les résultats de référence. Cela peut-être une requête, une vue ou une CTE (Common Table Expression). Dans mon exemple, la source contient des aliments (fruits, légumes, viandes…) et un statut permettant de savoir si celui-ci est disponible à la vente ou non (0 = non ; 1 = oui).
Id Name Category Statut
2 Carotte Légumes 1
3 Pomme Fruits 0
4 Mangue Fruits 1
5 Banane Fruits 0
6 Framboise Fruits 1
7 Fraise Fruits 0
8 Nectarine Fruits 1
9 Courgette Légumes 1
10 Concombre Légumes 0
11 Choux Légumes 0

  • Une table cible, sur laquelle viendront s’appliquer les opérations (INSERT, UPDATE et DELETE).
Id Name Category
1 Ananas Fruits
2 Poivron Légumes

  • Une ou plusieurs conditions de jointure qui permettent de définir comment sont rapprochées les lignes entre la source et la cible (équivalent du JOIN). Généralement, on utilise les clés primaires et/ou étrangères des tables concernées (il faut que ce soit un identifiant unique). Attention, cette clause ON n’est pas un filtre, elle est uniquement utilisée pour déterminer la clause WHEN à activer. Si vous devez faire du filtrage, il faut le faire directement au niveau de la source. Dans mon exemple, c’est ce que j’ai fait avec la clause WHERE [Statut] = 1  pour indiquer que je ne souhaite que les aliments disponibles à la vente.

  • Une ou plusieurs opérations DML en fonction du résultat de la jointure qui peut être de 3 types :

– MATCHED : la ligne correspond exactement aux conditions de jointures. Elles sont donc communes entre la cible et la source. Généralement, cela va déboucher sur une opération d’UPDATE. Il est possible d’avoir 2 clauses WHEN MATCHED, mais dans ce cas, la 1ère doit être accompagnée d’une clause AND et l’une doit produire un UPDATE, l’autre un DELETE. L’instruction MERGE ne peut pas mettre à jour ou supprimer la même ligne plusieurs fois.

– NOT MATCHED (BY TARGET) : la ligne de la source ne matchent pas avec la cible. Dans ce cas, on va généralement réaliser une opération d’INSERT.

– NOT MATCHED BY SOURCE : la ligne de la cible n’est pas présente dans la source. Si l’objectif est de faire une synchronisation de la source vers la cible, alors on va utiliser une opération de DELETE. Il est possible d’avoir 2 clauses WHEN NOT MATCHED BY SOURCE (même condition que pour le WHEN MATCH).

  • Au moins l’une de ces 3 clauses doit obligatoirement être spécifiée et l’ordre n’importe pas.
  • De manière optionnelle, une clause OUTPUT permet de tracer les actions réalisées par l’instruction MERGE (pour historiser ou logger par exemple)

Voilà le résultat suite à l’exécution de l’instruction MERGE :

Action Id Name Category Explication
INSERT 3 Mangue Fruits L’entité était présente dans la source mais pas dans la cible. On réalise donc une insertion.
INSERT 4 Framboise Fruits
INSERT 5 Nectarine Fruits
INSERT 6 Courgette Légumes
DELETE 1 Ananas Fruits L’entité n’était pas présente dans la source, on la supprime.
UPDATE 2 Carotte Légumes Le même ID existait dans la source et dans la cible, mais avec un nom différent (~poivron). On réalise donc une mise à jour.

Voici ce que nous retourne la table « Cart » :

Id Name Category
2 Carotte Légumes
3 Mangue Fruits
4 Franboise Fruits
5 Nectarine Fruits
6 Courgette Légumes

 

Je vais conclure par les aspects performances. L’instruction MERGE est un peu plus couteuse que son équivalent INSERT/UPDATE, mais le gain en confort, en sécurité et en simplicité vient, pour moi, contrebalancer cela (hors processus sensible ou demandant des performances de 1er ordre). Pour optimiser les performances, faites bien attention à créer correctement vos index, notamment sur les colonnes du JOIN (au niveau de la source ET de la cible). Microsoft documente d’ailleurs assez bien tous ces aspects.

Matthieu Anceret

Ingénieur en informatique chez C2S (groupe Bouygues), je suis passionné par tout ce qui touche à la technologie et la mobilité, et plus particulièrement à l'univers Android. Féru de domotique et de ses aspects multimédia, la moindre occasion est bonne pour tester et expérimenter les dernières nouveautés dans ce domaine. À travers ce blog, j'espère vous transmettre ma passion et mes connaissances. Bonne lecture !

Vous aimerez aussi...

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

%d blogueurs aiment cette page :