仅在连接临时表时,游标中的TSQL无限循环

时间:2013-12-20 00:25:41

标签: sql-server tsql cursor infinite-loop

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

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

现在,由于我的SP更新了很多不同的表(附加只是其中的一部分),并且在每次更新中我都使用了用户函数的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

谢谢!

1 个答案:

答案 0 :(得分:0)

我认为米奇是对的,你不应该使用光标。在进行更新时,如果您加入主键,则速度最快,因此您可以执行此类操作。

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