CURSOR不适用于SQL Server中的DECLARED表

时间:2012-09-13 03:48:40

标签: sql sql-server sql-server-2012

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

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

// 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

3 个答案:

答案 0 :(得分:1)

由于表A上的未提交事务,表A可能已被锁定。所以对于你的数据集游标try-

select '' from A with (nolock) where ...

答案 1 :(得分:1)

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

DECLARE cursor_name CURSOR FOR SELECT id INTO temp_table FROM user_id

答案 2 :(得分:1)

这是OP问题的可运行版本 - 但它没有表现出问题。这不是答案,所以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