无法在READ ONLY游标上指定FOR UPDATE

时间:2011-12-13 19:52:34

标签: sql sql-server tsql sql-server-2000

我使用游标更新表格中的单个字段,并且我尝试使用选择文本中的ORDER BY来声明游标。

我有以下示例数据:

testTable:
RecordGuid RecordID DupeParentID
---------- -------- ------------
[guid]     A        Y
[guid]     A        N
[guid]     A        N
[guid]     A        N
[guid]     B        Y
[guid]     B        N
[guid]     B        N
[guid]     C        Y
[guid]     C        N
[guid]     C        N

脚本:

DECLARE @allcounter INT
SET @allcounter = 1

SELECT RecordID, count(*) as [NumberDupes]
INTO #RecordGroupCounts
FROM testTable
GROUP BY RecordID

DECLARE @temp VARCHAR(500)
DECLARE @current VARCHAR(500)

DECLARE c1 CURSOR 
FOR 
    SELECT RecordID FROM testTable WHERE RecordID IN (SELECT RecordID FROM testTable WHERE DupeParentID = 'Y') 
    ORDER BY RecordID
FOR UPDATE OF RecordID

OPEN c1

FETCH NEXT FROM c1 INTO @current
FETCH NEXT FROM c1 INTO @current

WHILE @@fetch_status = 0
BEGIN
    UPDATE testTable
    SET RecordID = RecordID + '-' + cast(@allcounter AS VARCHAR)
    WHERE CURRENT OF c1

    IF (@allcounter + 1) = (SELECT [NumberDupes] FROM #RecordGroupCounts WHERE RecordID = @current)
    BEGIN
        FETCH NEXT FROM c1 INTO @current
        SET @allcounter = 0
    END 
    SET @allcounter = @allcounter + 1

    FETCH NEXT FROM c1 INTO @current
END
CLOSE c1
DEALLOCATE c1

所有这些的理想输出是:

RecordGuid RecordID DupeParentID
---------- -------- ------------
[guid]     A        Y
[guid]     A-1      N
[guid]     A-2      N
[guid]     A-3      N
[guid]     B        Y
[guid]     B-1      N
[guid]     B-2      N
[guid]     C        Y
[guid]     C-1      N
[guid]     C-2      N

我正在使用SQL Server 2000,因此我没有ROW_NUMBER()可用 - 我知道执行此操作的常用方法是使用循环,但我绝不是DBA,并且如果我在游标声明中删除ORDER BY RecordID,这当前有效。

由于我目前的测试表一样小,这似乎工作正常,但我试图订购这个的原因是我相当肯定如果RecordIDs不是&它会中断按顺序排列(按RecordID ASC, DupeParentID DESC),我打算半定期地在更大的记录集上使用它。有没有办法定义更新的游标的顺序?光标是否以某种方式自动排序?如果没有,是否有更简单(或更快)的方法为SQL Server 2000写这个?

2 个答案:

答案 0 :(得分:2)

select recordid, max(recordguid)
from testable
where DupeParentID = 'N'
group by recordID

上述语句应该为每个recordID返回1行,其中包含该recordID的max(guID)。嘿,拼写检查不断改变guid指导。现在我们可以用1增加所有这些。

update testtable 
set recordID = recordID + '-1'
where recordguid in (select recordguid from (    select recordid, max(recordguid) recordguid
from testable
where DupeParentID = 'N'
group by recordID) a)

在这里获取逻辑?我们正在做的是使用max recordguid作为'first'的标识符来获取第一个重复ID ... lil任意,我们可以使用min以及只为每个recordID返回一个guID。如果你有一些关于哪个记录被称为-1对-2的其他逻辑,你可以在这里包含它。

这将创建所有recordID-1(A-1,B-1)并将其余部分单独留下。现在你应该能够循环这个并根据需要增加-1 ...或者你可以重复运行它自己递增-1如果这是一次修复...你的呼叫那里。

让我知道它是怎么回事......逻辑应该起作用,并且比一次遍历每个recordID要快得多。

答案 1 :(得分:1)

您可以尝试以下操作。虽然我不希望性能变得很好,但如果你需要定期运行生产查询,我不会推荐这个解决方案。

declare @counter int ,@continue tinyint
set @counter =1 
set @continue = 1
while @continue = 1
Begin 
    update testtable 
    set testtable.recordid = testtable.recordid + ' - ' + CAST (@counter as nchar(6))
    from 
    testtable 
    inner join
    (  
    select  MAX(cast(t1.guid as char(36)))  as maxguid from testtable t1
    inner join testtable t2 on t1.recordid = t2.recordid 
    where
    t2.dupeparentid = 'y' and  t1.dupeparentid = 'n'
    group by t1.recordid
    ) t4

    on testtable.guid = cast (t4.maxguid as uniqueidentifier)

    if @@ROWCOUNT = 0 
    set @continue = 0
    set @counter = @counter + 1
end