2009-03-31 2 views
0

некоторые примерные данные:SQL: Как ограничить количество записей оператор MERGE будет вставлять

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 

Так что я, имеющий целевую таблицу и таблицу источника. То, что я хочу сделать, состоит в том, что, когда имеется большое количество элементов not matched, нужно вставлять только верхние элементы x с наивысшим значением.
Использование сверху на слиянии сами не будет работать, потому что ограничил бы таблицу всей исходную, я хочу сделать что-то вроде

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) 

---- UPDATE ----
Моего MERGE заявления также содержит КОГДА MATCHED ТОГДА заявление:

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

это, к сожалению, нивелирует ответы, данные Яна и собака ...

ответ

2

Не SET ROWCOUNT DEPRECATED, вы можете использовать верхний пункт, если вы делаете это так:

;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 

Поручения ИНТ слияния обыкновение работайте, если у вас нет предложения TOP, поэтому использование TOP (100) PERCENT делает SQL-запросы для разрешения заказа.

Edit:

Что делать это в два этапа?

;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

Вы правы в том, что SET ROWCOUNT устарела. В моем комментарии к Ian Quigley я написал, что мой пример упрощен и не учитывает тот факт, что у меня также есть инструкция WHEN MATCHED THEN, которая обновляет цель. Обновление должно происходить во всех согласованных записях, вставка должна только ... – Gidon

+0

... произойти на вершине x записей с самым высоким значением. Ваш пример будет работать, если у меня не будет другого требования. – Gidon

+0

Как сделать это в два этапа, см. Исправленный ответ. –

2

Вы можете использовать SET ROWCOUNT n;

Например,

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

См. http://msdn.microsoft.com/en-us/library/ms188774.aspx

Или вы можете сделать

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

Я написал комментарий, прежде чем StackOverflow разбился ... и стер этот комментарий, и некоторые другие замечания по другим вопросам :-( в любом случае я упростил пример, есть и когда подобрано ТОГДА, который должен всегда Обновление с использованием rowcount, вначале оно должно было бы выполнить WHEN MATCHED, а если есть ... – Gidon

+0

... меньше строк, обновленных, а затем указано в строке, это будет INSERT в КОГДА НЕ СКАЗАНО ТОГДА. Это не то, что я хочу , Я хочу ограничить только INSERT, а не UPDATEs – Gidon

+0

Не знаком с «murge», я бы подумал о том, «где s.id not in (select id from @source). Вы даже можете сделать это с помощью трюка, правая сторона - нуль..Meh .. :) –

Смежные вопросы