1

在我的 sql 代码中,我声明了一个表(A)并从数据库表(B)中向该表中插入了一些行。然后我必须从 A 中取出那些插入的行并将其放入 CURSOR 中,然后在我执行完之后FETCH NEXT仍然是@@FETCH_STATUSis -1。但 的期望值@@FETCH_STATUS0。我在问题下面放了一个简化的代码。

我能知道这段代码有什么问题吗?我可以使用声明的表来填充CURSORSQL 中的 s 还是必须从数据库中创建的表中填充游标。

// This is a code that goes inside a Stored Procedure.

AS
   DECLARE A TABLE (.........)// A table has same fields in table B
   DECLARE s INT

   WHILE EXISTS ( SELECT * FROM B WHERE ......)
   BEGIN
      BEGIN TRAN
      INSERT INTO A SELECT TOP 10 (....)FROM B WITH (UPDLOCK, HOLDLOCK) WHERE ....

      SELECT s = count(*) from A // this returns some value which means inserting is working 
      DECLARE  dataSet CURSOR FOR (SELECT..... FROM A)
      OPEN dataSet
      FETCH NEXT FROM dataSet INTO ...

       WHILE @@FETCH_STATUS = 0 // coming value for this is -1
       BEGIN
          //Code goes here
          FETCH NEXT FROM dataSet INTO ...
        END

   CLOSE dataSet
   DEALLOCATE dataSet
   DELETE FROM A
   COMMIT TRAN
END
4

3 回答 3

1

由于表 A 上的未提交事务,表 A 可能已被锁定。因此,对于您的数据集游标尝试-

select '' from A with (nolock) where ...
于 2012-09-13T04:12:50.200 回答
1

我认为创建临时表然后将其声明为游标,而不是必须有一个现有的表,如:

DECLARE cursor_name CURSOR FOR SELECT id INTO temp_table FROM user_id
于 2012-09-13T04:14:13.687 回答
1

这是 OPs 问题的可运行版本 - 但它没有显示问题。这不是答案,所以 CW,如果/当 OP 确实发布了一个实际示例,我将删除:

create table B (ID int not null,Val1 varchar(10) not null)
go
insert into B(ID,Val1) values (1,'abc'),(2,'ade')
go
create procedure DoStuff
AS
   DECLARE @A TABLE (ID int not null,Val1 varchar(10) not null)
   DECLARE @s INT

   WHILE EXISTS ( SELECT * FROM B WHERE Val1 like 'a%')
   BEGIN
      BEGIN TRAN
      INSERT INTO @A SELECT TOP 10 ID,Val1 FROM B WITH (UPDLOCK, HOLDLOCK) WHERE Val1 like 'a%'

      SELECT @s = count(*) from @A
      DECLARE dataSet CURSOR FOR (SELECT ID,Val1 FROM @A)
      declare @ID int
      declare @Val1 varchar(10)
      OPEN dataSet
      FETCH NEXT FROM dataSet INTO @ID,@Val1

       WHILE @@FETCH_STATUS = 0
       BEGIN
          RAISERROR('%i: %s',10,1,@ID,@Val1) WITH NOWAIT
          UPDATE B set Val1 = 'done' where ID = @ID
          FETCH NEXT FROM dataSet INTO @ID,@Val1
        END

   CLOSE dataSet
   DEALLOCATE dataSet
   DELETE FROM @A
   COMMIT TRAN
END
GO
EXEC DoStuff
GO
SELECT * from B

输出:

(2 row(s) affected)

(2 row(s) affected)
1: abc

(1 row(s) affected)
2: ade

(1 row(s) affected)

(2 row(s) affected)

(2 row(s) affected)

和表B

ID  Val1
1   done
2   done
于 2012-09-13T06:47:30.113 回答