SQL:如何限制MERGE语句将插入的记录数

时间:2009-03-31 08:42:08

标签: sql-server tsql merge filter

一些示例数据:

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顶部项目。
在合并上使用top不起作用,因为这会限制整个源表,我想做类似

的操作
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)

----更新----
我的MERGE语句还包含一个WHEN MATCHED THEN语句:

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

这令人遗憾地否定了Ian和Dog给出的答案......

2 个答案:

答案 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.

答案 1 :(得分:2)

不是SET ROWCOUNT已弃用,如果您这样做,可以使用top子句:

;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子句,否则合并中的ORDER BY不会工作,所以使用TOP(100)PERCENT欺骗SQL以允许排序。

编辑:

如何分两步完成?

;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