web-dev-qa-db-fra.com

Lorsque vous utilisez plusieurs instructions WHEN MATCHED, sont-elles toutes exécutées ou une seule est-elle exécutée?

Si j'ai plusieurs instructions WHEN MATCHED dans une instruction MERGE, sont-elles toutes exécutées si elles sont vraies?

Mon exemple:

DECLARE @X bit = NULL;

--skipping the MERGE statement, straight to WHEN MATCHED

WHEN MATCHED AND A = 1
    @X = 0;
WHEN MATCHED AND B = 1
    @X = 1;

Quel est l'état de X dans chacune des 4 possibilités?

A|B|X
0|0|?
0|1|?
1|0|?
1|1|?

En gros, je suis curieux de savoir s’il existe une pause implicite après chaque clause WHEN MATCHED.

17
Codeman

Pour répondre à votre question, oui, il n'y aura qu'un match, puis une pause. Toutefois, si vous souhaitez que la logique permette la mise en correspondance conditionnelle dans la mise à jour, l'instruction CASE est plutôt utile pour cela.

Quelque chose comme ça à titre d'exemple:

MERGE INTO YourTable
USING (VALUES (1, 1, NULL), (0, 0, NULL), (0, 1, NULL), (1, 0, NULL))
       T2 (a2,b2,c2)
ON a = a2 AND b = b2
WHEN MATCHED  THEN
    UPDATE SET c = 
      CASE 
        WHEN a = 1 THEN 0
        WHEN b = 1 THEN 1
        ELSE NULL
      END        
WHEN NOT MATCHED THEN
    INSERT (a, b) VALUES (a2, b2);

SELECT * FROM YourTable ORDER BY a,b;

Et les résultats:

A   B   C
--------------
0   0   (null)
0   1   1
1   0   0
1   1   0
13
sgeddes

J'ai trouvé dans la documentation MSDN :

QUAND S'ADAPTE ALORS 

Spécifie que toutes les lignes de target_table qui correspondent aux lignes renvoyées par ON et satisfont à toute condition de recherche supplémentaire sont mises à jour ou supprimées conformément à la clause.

L'instruction MERGE peut comporter au maximum deux clauses WHEN MATCHED. Si deux clauses sont spécifiées, la première clause doit être accompagnée d'une clause AND. Pour une ligne donnée, la seconde clause WHEN MATCHED n'est appliquée que si la première ne l'est pas. S'il existe deux clauses WHEN MATCHED, l'une doit spécifier une action UPDATE et l'autre, une action DELETE. Si UPDATE est spécifié dans la clause et que plusieurs lignes correspondent à une ligne de target_table, SQL Server renvoie une erreur. L'instruction MERGE ne peut pas mettre à jour la même ligne plus d'une fois, ni mettre à jour et supprimer la même ligne.

Il semble donc qu’une seule des instructions soit exécutée et qu’elles nécessitent un DELETE dans l’une et une UPDATE dans l’autre.

18
Codeman

eh bien, la réponse est: voulez-vous vraiment le faire, car si vous le faisiez, vous changeriez une mise à jour basée sur un ensemble en agonisant comme une mise à jour lente comme dans un ensemble de lignes, vous ne sauriez vraiment pas quelles colonnes ont été modifiées enregistrement par enregistrement .

la question est donc de savoir si vous souhaitez obtenir des performances. Si tel est le cas, assurez-vous d’avoir des index couvrant la 

WHEN MATCHED TARGET.FIELD1 = SOURCE:FIELD1 AND TARGET.FIELD2 = SOURCE:FIELD2 ... 

sinon, vous devrez passer la souris sur vos mises à jour après la fusion en utilisant un déclencheur INSTEAD OF ...

Pas bon pour la vitesse, cependant, peut fonctionner si vous devez enregistrer qui a fait quoi ... 

Code heureux

Walter

0
Walter Verhoeven