游标是执行此类操作的唯一选择吗

发布于 2024-12-05 22:03:17 字数 956 浏览 0 评论 0原文

我正在尝试优化一个长事务,并且我已经看到以下操作完成了很多次:

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 存储过程的代码如下:

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

就像我提到的,这是在很多地方完成的,涉及表和字段不同,但想法保持不变,并且我确信,如果不使用游标,可能有一种方法可以提高这些存储过程的性能,并且可能通过使此事务更快,这是我们遇到的死锁问题(一个主题另一篇文章)可能会得到解决。

I'm trying to optimize a long transaction and I've seen that the following is done quite a few times:

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

The code for the USP_SOME_PROC sproc is as follows:

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

Like I mentioned this is done in quite a few places, tables and fields involved are different but the idea remains the same, and I'm sure that there might be a way to increase the performance of these sprocs if cursors are not used and probably by making this transaction faster an issue that we're having with a deadlock (a subject for another post) might be solved.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

独闯女儿国 2024-12-12 22:03:17

您可以使用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)
    ;

You can use MERGE for this

;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)
    ;
妞丶爷亲个 2024-12-12 22:03:17

我还没有机会测试这一点,但这应该很接近:您需要从 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 

I haven't had a chance to test this, but this should be close: you need to insert from a SELECT statement but also need to make sure that a corresponding record doesn't already exist in 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 
写下不归期 2024-12-12 22:03:17

您不需要有光标,可以使用批量插入逻辑,如下所示

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

希望这有帮助!

You need not have a cursor and can use bulk insert logic something like below

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

Hope this helps!!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文