2009-03-31 9 views
0

Certaines données de l'échantillon:SQL: Comment limiter le nombre d'enregistrements l'instruction MERGE insérera

DECLARE @TARGET TABLE (ID INT, value INT) ; 
DECLARE @SOURCE TABLE (ID INT, value INT) 

INSERT INTO @TARGET VALUES (1, 213)    
INSERT INTO @TARGET VALUES (2, 3)    
INSERT INTO @TARGET VALUES (3, 310)    
INSERT INTO @TARGET VALUES (4, 43)      

INSERT INTO @SOURCE VALUES (1, 134)    
INSERT INTO @SOURCE VALUES (2, 34)    
INSERT INTO @SOURCE VALUES (13, 310)    
INSERT INTO @SOURCE VALUES (14, 43)    
INSERT INTO @SOURCE VALUES (15,32)    
INSERT INTO @SOURCE VALUES (16, 30)    
INSERT INTO @SOURCE VALUES (17, 60)    
INSERT INTO @SOURCE VALUES (18, 5)     


MERGE @TARGET t USING (SELECT * FROM @SOURCE) AS s ON (t.id = s.id) 
WHEN NOT MATCHED THEN 
INSERT VALUES (s.id,s.value); 

SELECT * FROM @TARGET 

Je vais avoir une table cible, et une table source. Ce que je veux accomplir est que quand il y a un grand nombre de not matched articles, pour insérer seulement les articles du haut x avec la valeur la plus élevée.
En utilisant la fusion supérieure sur elle-même ne fonctionnera pas, car cela limiterait l'ensemble table source, je veux faire quelque chose comme

WHEN NOT MATCHED 
LIMIT(5) AND ORDER BY Value DESC --only insert the 5 non-matches with the highest value 
INSERT VALUES (s.id,s.value) 

---- ---- ACTUALISATION
Mon instruction MERGE aussi contient une THEN, égalés:

WHEN MATCHED THEN 
UPDATE SET t.value = s.value 

cette nie malheureusement les réponses données par Ian et Dog ...

Répondre

2

Is not SET ROWCOUNT Obsolète, vous pouvez utiliser la clause top si vous le faites comme ceci:

;MERGE TOP (5) @TARGET t USING 
(SELECT TOP (100) PERCENT * FROM @SOURCE ORDER BY VALUE DESC) AS s ON (t.id = s.id) 
WHEN NOT MATCHED 
THEN 
INSERT VALUES (s.id,s.value); 

SELECT * FROM @TARGET 

ORDER BY int la fusion wont travailler à moins d'avoir une clause TOP, en utilisant TOP (100) PERCENT astuces SQL en permettant la commande.

Edit:

Qu'en est-il fait en deux étapes?

;MERGE TOP (5) @TARGET t USING 
(SELECT TOP (100) PERCENT * FROM @SOURCE ORDER BY VALUE DESC) AS s ON (t.id = s.id) 
WHEN NOT MATCHED 
THEN 
INSERT VALUES (s.id,s.value);/* 
WHEN MATCHED THEN 
UPDATE SET t.value = s.value;*/ 

update t 
set t.Value = s.Value 
from  @Target t 
    join @Source s on t.ID = s.ID 
where t.Value <> s.Value 

SELECT * FROM @TARGET 
+0

vous avez raison sur le SET ROWCOUNT étant obsolète. Dans mon commentaire à Ian Quigley, j'ai écrit que mon exemple est trop simplifié, et a omis le fait que j'ai aussi une instruction WHEN MATCHED THEN qui met à jour la cible. La mise à jour doit se produire sur tous les enregistrements correspondants, l'insertion doit uniquement ... – Gidon

+0

... se produire sur les x premiers enregistrements avec la valeur la plus élevée. Votre exemple fonctionnerait si je n'avais pas l'autre exigence. – Gidon

+0

Que faire en deux étapes voir la réponse modifiée. –

2

Vous pouvez utiliser SET ROWCOUNT n;

Par exemple;

SET ROWCOUNT 4; 
UPDATE Production.ProductInventory 
SET Quantity = 400 
WHERE Quantity < 300; 

Voir; http://msdn.microsoft.com/en-us/library/ms188774.aspx

Ou vous pouvez faire

Insert to @Target 
Select top 5 s.id, s.value from @Source s 
order by s.value desc ... etc. 
+0

j'ai écrit un commentaire avant stackoverflow ... et écrasé effacer ce commentaire, et d'autres commentaires sur les questions autres :-( de toute façon je l'exemple simplifié à l'extrême, il y a aussi un QUAND ensuite recoupé, qui devrait toujours En utilisant le rowcount, il ferait d'abord le WHEN MATCHED et s'il y a ... – Gidon

+0

... moins les lignes mises à jour puis indiquées dans le rowcount, il va INSÉRER dans le QUAND PAS CORRESPONDU .. Ce n'est pas ce que je veux , Je veux limiter seulement l'INSERT et pas les UPDATEs – Gidon

+0

Pas familier avec "murge", je penserais à faire "où il n'est pas dans (sélectionnez l'id de @ source). Vous pourriez même faire cela avec une jointure de tour où le côté droit est null..Meh .. :) –

Questions connexes