【问题标题】:TSQL infinite loop in cursor when joining temp table only仅加入临时表时游标中的 SQL 无限循环
【发布时间】:2013-12-20 00:25:40
【问题描述】:

我有一个 SP,它使用 CURSOR 和 FETCH NEXT 更新表中的价格。

光标的查询是一个简单的“选择”,而不是 WHERE - 我加入了一个函数,该函数会带来所有相关的用户 ID。

现在,由于我的 SP 更新了很多不同的表(附件只是其中的一部分),并且在每次更新中我都使用了 users 函数的 JOIN - 我想节省一些时间,并带来用户只列出一次,在 SP 的开头。

如果我加入我的临时表(@t,其中包含用户 ID),我会得到一个无限循环。 最终价格将是无限的。

但是 - 如果我加入函数本身,而不是应该在其中具有完全相同值的临时表,一切都很好。

我评论了有问题的 JOIN。

-- This is my main object, who "holds" a lot of users
DECLARE @DistID INT = 123

DECLARE @t TABLE
(MainDistID int,
 DistID int,
 UserID int)

INSERT INTO @t

SELECT MainDistID,
       DistID,
       UserID
FROM [MyScheme].[FnGetAllDistAndUsers] (@DistID)

DECLARE @Bid INT -- Will contain the ID we need to update

DECLARE c CURSOR LOCAL FOR 
SELECT ID
FROM BillingDetails AS bd
-- BOTH JOINS SHOULD BE THE SAME:
--JOIN @t AS GUsers -- Infinite loop...
--  ON bd.UserID = GUsers.UserID
JOIN [MyScheme].[FnGetAllDistAndUsers] (@DistID) AS GUsers -- NO infinite loop
    ON bd.UserID = GUsers.UserID

OPEN c

FETCH NEXT FROM c
INTO @Bid

WHILE @@FETCH_STATUS = 0
BEGIN
    UPDATE MyTable
    SET Price = Price * 2
    WHERE MyTableID = @Bid

    FETCH NEXT FROM c
    INTO @Bid
END

谢谢!

【问题讨论】:

  • 我很确定您不需要使用光标。
  • 米奇,我使用游标来防止锁定(更新 100,000 行)。这是我数据库中最繁忙的表。我不将游标用于我的 SP 中的所有其他更新。所以我确实需要使用它。谢谢。
  • 您是否尝试过在循环中使用 PRINT 运行它以了解哪里出错了?你可以折腾一个额外的 WHERE 条件,例如UserId % 100 = 42 减少分析行数。
  • 如果您的意思是“我正在批量执行以防止阻塞”,请参阅我的第一条评论。
  • Mitch,我运行了 2 个测试: 1. 使用用户 ID 的 JOIN 在一个批次/操作中更新所有 100,000 行。在 35 秒内完成,但锁定了表格,我无法从中选择/插入。 2. 使用游标一次更新一行并获取下一个。 5 分钟内完成(是),但没有锁定桌子。如何在不锁定表(并且不使用光标)的情况下进行此更新?

标签: sql-server tsql cursor infinite-loop


【解决方案1】:

我认为 Mitch 是对的,您不应该使用光标。进行更新时,如果您加入主键,则速度最快,因此您可以这样做。

DECLARE @t TABLE (Bid int)

INSERT INTO @t
SELECT bd.ID
FROM [MyScheme].[FnGetAllDistAndUsers] u (@DistID)
INNER JOIN BillingDetails bd
    ON u.UserID = bd.UserID

UPDATE mt
SET Price = Price * 2
FROM MyTable mt
INNER JOIN @t t
    ON mt.MyTableID = t.Bid

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-06
    • 2011-06-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多