无法在 READ ONLY 游标上指定 FOR UPDATE
我正在使用游标来更新表中的单个字段,并尝试在选择文本中使用 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
,则当前可以使用此方法。
对于我当前的测试表来说,这似乎工作得很好,但我尝试订购它的原因是,我相当确定如果 RecordID 不按顺序,它就会中断(通过 RecordID ASC、DupeParentID DESC
),我打算半定期地在更大的记录集上使用它。有没有办法定义游标更新的顺序?光标是否以某种方式自动排序?如果没有,是否有更简单(或更快)的方法为 SQL Server 2000 编写此代码?
I'm using a cursor to update a single field in a table, and I'm attempting to declare the cursor using an ORDER BY
in the text of the select.
I've got the following example data:
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
And script:
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
The desired output of all of this is:
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
I'm working with SQL Server 2000 so I don't have ROW_NUMBER()
available - I know the common way to do this is with loops, but I am by no means a DBA, and this currently works if I remove my ORDER BY RecordID
in the cursor declaration.
With as small as my current test table is this seems to be working fine, but the reason I'm attempting to order this is that I'm fairly sure it'll break if the RecordIDs aren't in order (by RecordID ASC, DupeParentID DESC
) and I intend to use this on a much larger set of records semi-regularly. Is there a way to define the order for a cursor that updates? Is the cursor ordered automatically somehow? If not, is there a simpler (or faster) way to write this for SQL Server 2000?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
上述语句应为每个 recordID 返回 1 行,其中包含该 recordID 的 max(guID)。呵呵,拼写检查不断改变指南。现在我们可以用 1 来增加所有这些。
明白这里的逻辑了吗?我们正在做的是使用 max recordguid 作为“第一个”的标识符来获取第一个重复 ID...任意,我们可以使用 min,只要它为每个 recordID 返回一个 guID。如果您对于哪条记录被称为 -1 与 -2 有其他逻辑,您可以将其包含在此处。
这将创建所有 recordID-1 (A-1,B-1) 并保留其余部分。现在你应该能够循环这个并根据需要增加 -1...或者你可以重复运行它,手动增加 -1 如果这是一次性修复...你在那里打电话。
让我知道它是如何进行的...逻辑应该有效并且比一次遍历每个 recordID 更快。
The above statement should return 1 row per recordID with the max(guID) for that recordID. heh, spell check keeps changing guid to guide. Now we can increment all of these with the 1.
Get the logic here? What we're doing is taking the first duplicate ID using the max recordguid as an identifier for the 'first'...lil arbitrary, we could use min as well as long as it returns just one guID for each recordID. If you had some other logic as to which record was to be called the -1 vs the -2, you can include it here.
This will create all the recordID-1 (A-1,B-1) and leave the rest alone. Now you should be able to loop this and increment the -1 as needed...or you could just repeat run it manually incrementing the -1 yourself if this is a one time fix...your call there.
Let me know how it goes...the logic should work and will be quite quicker than going through each recordID at a time.
您可以尝试以下操作。尽管我不期望性能太好,所以如果您需要定期在生产中运行查询,我不会推荐此解决方案。
You can try the following. Although I do not expect performance to be to great, so I would not recomend this solution if you need to run the query on production on regular basis.