光标是执行此类操作的唯一替代方法

时间:2011-09-21 15:22:29

标签: sql-server sql-server-2008 database-cursor

我正在尝试优化长期交易,并且我已经看到以下几次完成:

Declare @myCursor CURSOR FAST_FORWARD FOR
SELECT field1, MIN(COALESCE(field2, -2)) FROM MyTable tempfact
LEFT JOIN MyTable sd
ON tempfact.ID = sd.ID AND sd.TransactionId = @transactionId
WHERE tempfact.SomeField IS NULL
AND tempfact.TransactionId = @transactionId
GROUP BY tempfact.field1

OPEN @myCursor

FETCH NEXT FROM @myCursor INTO @field1Variable, @field2Variable

WHILE @@FETCH_STATUS = 0
BEGIN
   EXEC USP_SOME_PROC @field1Variable, @field2Variable
   FETCH NEXT FROM @myCursor INTO @field1Variable, @field2Variable
END

CLOSE @myCursor
DEALLOCATE @myCursor

USP_SOME_PROC sproc的代码如下:

IF NOT EXISTS (SELECT * FROM SomeTable WHERE Field1 = @field1)
BEGIN
   INSERT INTO SomeTable (Field1, Field2)
   VALUES (@field1, @field2)
END

就像我提到的那样,这在很多地方完成,所涉及的表和字段不同但想法保持不变,而且我确信如果游标不是,那么可能有办法提高这些sprocs的性能使用和可能通过使这个事务更快,我们遇到的死锁问题(另一个帖子的主题)可能会被解决。

3 个答案:

答案 0 :(得分:4)

您可以将MERGE用于此

;WITH Source AS
(
SELECT field1,
       MIN(COALESCE(field2, -2)) as field2
FROM   MyTable tempfact
       LEFT JOIN MyTable sd
         ON tempfact.ID = sd.ID
            AND sd.TransactionId = @transactionId
WHERE  tempfact.SomeField IS NULL
       AND tempfact.TransactionId = @transactionId
GROUP  BY tempfact.field1  
)
MERGE SomeTable AS T
USING Source S
ON (T.Field1 = S.Field1)


WHEN NOT MATCHED BY TARGET THEN
    INSERT (Field1, Field2)
    VALUES (field1, field2)
    ;

答案 1 :(得分:1)

我没有机会对此进行测试,但这应该是关闭的:您需要从SELECT语句插入,但还需要确保SomeTable中不存在相应的记录

INSERT INTO SomeTable (Field1, Field2)
SELECT field1, MIN(COALESCE(field2, -2)) 
FROM MyTable tempfact 
    LEFT JOIN MyTable sd ON tempfact.ID = sd.ID AND sd.TransactionId = @transactionId 
    LEFT JOIN SomeTable st ON st.Field1 = tempfact.field1
WHERE tempfact.SomeField IS NULL 
    AND tempfact.TransactionId = @transactionId 
    AND st.Field1 IS NULL
GROUP BY tempfact.field1 

答案 2 :(得分:0)

您不需要光标,可以使用下面的批量插入逻辑

INSERT INTO SomeTable (Field1, Field2) 
SELECT 
       field1,       
       MIN(COALESCE(field2, -2)) 
FROM
      MyTable tempfact        
LEFT JOIN 
      MyTable sd          
           ON tempfact.ID = sd.ID             
              AND sd.TransactionId = @transactionId 
WHERE  
      tempfact.SomeField IS NULL        
      AND tempfact.TransactionId = @transactionId 
GROUP  BY 
      tempfact.field1

希望这会有所帮助!!