主要问题是将行的索引更改为1,2,3 ..其中contact-id和type是相同的.但是所有列都可以包含完全相同的数据,因为一些前雇员搞砸了并通过contact-id和type更新所有行.不知何故,有些行没有混乱,但索引行是相同的.这完全是混乱.
我试图使用一个带有来自外部光标的变量的内部游标.但似乎它卡在内部光标中.
查询的一部分如下所示:
Fetch NEXT FROM OUTER_CURSOR INTO @CONTACT_ID, @TYPE While (@@FETCH_STATUS <> -1) BEGIN IF (@@FETCH_STATUS <> -2) DECLARE INNER_CURSOR Cursor FOR SELECT * FROM CONTACTS where CONTACT_ID = @CONTACT_ID and TYPE = @TYPE Open INNER_CURSOR Fetch NEXT FROM INNER_CURSOR While (@@FETCH_STATUS <> -1) BEGIN IF (@@FETCH_STATUS <> -2)
可能是什么问题?是@@ FETCH_STATUS暧昧还是什么?
编辑:如果我不在内部游标内使用此代码,一切看起来很好:
UPDATE CONTACTS SET INDEX_NO = @COUNTER where current of INNER_CURSOR
编辑:这是大局:
BEGIN TRAN DECLARE @CONTACT_ID VARCHAR(15) DECLARE @TYPE VARCHAR(15) DECLARE @INDEX_NO SMALLINT DECLARE @COUNTER SMALLINT DECLARE @FETCH_STATUS INT DECLARE OUTER_CURSOR CURSOR FOR SELECT CONTACT_ID, TYPE, INDEX_NO FROM CONTACTS WHERE CONTACT_ID IN (SELECT CONTACT_ID FROM dbo.CONTACTS WHERE CONTACT_ID IN(...) GROUP BY CONTACT_ID, TYPE, INDEX_NO HAVING COUNT(*) > 1 OPEN OUTER_CURSOR FETCH NEXT FROM OUTER_CURSOR INTO @CONTACT_ID, @TYPE, @INDEX_NO WHILE (@@FETCH_STATUS <> -1) BEGIN IF (@@FETCH_STATUS <> -2) SET @COUNTER = 1 DECLARE INNER_CURSOR CURSOR FOR SELECT * FROM CONTACTS WHERE CONTACT_ID = @CONTACT_ID AND TYPE = @TYPE FOR UPDATE OPEN INNER_CURSOR FETCH NEXT FROM INNER_CURSOR WHILE (@@FETCH_STATUS <> -1) BEGIN IF (@@FETCH_STATUS <> -2) UPDATE CONTACTS SET INDEX_NO = @COUNTER WHERE CURRENT OF INNER_CURSOR SET @COUNTER = @COUNTER + 1 FETCH NEXT FROM INNER_CURSOR END CLOSE INNER_CURSOR DEALLOCATE INNER_CURSOR FETCH NEXT FROM OUTER_CURSOR INTO @CONTACT_ID, @TYPE, @INDEX_NO END CLOSE OUTER_CURSOR DEALLOCATE OUTER_CURSOR COMMIT TRAN
Mark Brittin.. 62
你有各种各样的问题.首先,为什么要使用特定的@@ FETCH_STATUS值?它应该是@@ FETCH_STATUS = 0.
其次,你不选择你的内心光标到任何东西.而且我想不出你会以这种方式选择所有领域的任何情况 - 将它们拼出来!
这是一个经过的样本.Folder的主键为"ClientID",也是Attend的外键.我只是打印所有的Attend UID,按文件夹ClientID分类:
Declare @ClientID int; Declare @UID int; DECLARE Cur1 CURSOR FOR SELECT ClientID From Folder; OPEN Cur1 FETCH NEXT FROM Cur1 INTO @ClientID; WHILE @@FETCH_STATUS = 0 BEGIN PRINT 'Processing ClientID: ' + Cast(@ClientID as Varchar); DECLARE Cur2 CURSOR FOR SELECT UID FROM Attend Where ClientID=@ClientID; OPEN Cur2; FETCH NEXT FROM Cur2 INTO @UID; WHILE @@FETCH_STATUS = 0 BEGIN PRINT 'Found UID: ' + Cast(@UID as Varchar); FETCH NEXT FROM Cur2 INTO @UID; END; CLOSE Cur2; DEALLOCATE Cur2; FETCH NEXT FROM Cur1 INTO @ClientID; END; PRINT 'DONE'; CLOSE Cur1; DEALLOCATE Cur1;
最后,你SURE你想要做这样的事情在存储过程中?滥用存储过程非常容易,并且通常会反映出表征问题的问题.例如,我给出的样本使用标准选择调用可以更容易地完成.
你有各种各样的问题.首先,为什么要使用特定的@@ FETCH_STATUS值?它应该是@@ FETCH_STATUS = 0.
其次,你不选择你的内心光标到任何东西.而且我想不出你会以这种方式选择所有领域的任何情况 - 将它们拼出来!
这是一个经过的样本.Folder的主键为"ClientID",也是Attend的外键.我只是打印所有的Attend UID,按文件夹ClientID分类:
Declare @ClientID int; Declare @UID int; DECLARE Cur1 CURSOR FOR SELECT ClientID From Folder; OPEN Cur1 FETCH NEXT FROM Cur1 INTO @ClientID; WHILE @@FETCH_STATUS = 0 BEGIN PRINT 'Processing ClientID: ' + Cast(@ClientID as Varchar); DECLARE Cur2 CURSOR FOR SELECT UID FROM Attend Where ClientID=@ClientID; OPEN Cur2; FETCH NEXT FROM Cur2 INTO @UID; WHILE @@FETCH_STATUS = 0 BEGIN PRINT 'Found UID: ' + Cast(@UID as Varchar); FETCH NEXT FROM Cur2 INTO @UID; END; CLOSE Cur2; DEALLOCATE Cur2; FETCH NEXT FROM Cur1 INTO @ClientID; END; PRINT 'DONE'; CLOSE Cur1; DEALLOCATE Cur1;
最后,你SURE你想要做这样的事情在存储过程中?滥用存储过程非常容易,并且通常会反映出表征问题的问题.例如,我给出的样本使用标准选择调用可以更容易地完成.
您还可以通过完全避免游标来回避嵌套游标问题,常规游标问题和全局变量问题.
declare @rowid int declare @rowid2 int declare @id int declare @type varchar(10) declare @rows int declare @rows2 int declare @outer table (rowid int identity(1,1), id int, type varchar(100)) declare @inner table (rowid int identity(1,1), clientid int, whatever int) insert into @outer (id, type) Select id, type from sometable select @rows = count(1) from @outer while (@rows > 0) Begin select top 1 @rowid = rowid, @id = id, @type = type from @outer insert into @innner (clientid, whatever ) select clientid whatever from contacts where contactid = @id select @rows2 = count(1) from @inner while (@rows2 > 0) Begin select top 1 /* stuff you want into some variables */ /* Other statements you want to execute */ delete from @inner where rowid = @rowid2 select @rows2 = count(1) from @inner End delete from @outer where rowid = @rowid select @rows = count(1) from @outer End