none
Setar cursor novamente para inicio RRS feed

  • Pergunta

  • Boa Tarde,

    Declarei um cursor, percorro ele com a condição while fazendo algumas operações, e quando termina, logo depois quero setar ele novamente para o inicio para executar outras operações sem precisar dar um close, deallocate e declarar ele novamente.

    Alguém sabe se isso é possível fazer?

    Obrigada

    quinta-feira, 19 de janeiro de 2012 20:16

Respostas

  • Juliana,

    caso você já tenha plena convicção que irá utilizar mesmo o cursor, segue um exemplo.

    Set Nocount on 
    
    Create Table Teste (Cod int)
    insert into Teste values(1)
    insert into Teste values(2)
    insert into Teste values(3)
    --
    Declare @Cod int
    --
    Declare CurTeste Cursor Scroll
    For   Select   Cod 
          From     Teste
    --
    Open CurTeste
    --
    Fetch Next From CurTeste
    Into @Cod
    --
    While @@FETCH_STATUS = 0
    Begin
       print @Cod
       --
       Fetch Next From CurTeste
       Into @Cod
    End
    --
    -- Retorna para a primeira linha
    --------------------------------------
    Fetch First From CurTeste
    Into @Cod
    
    While @@FETCH_STATUS = 0
    Begin
       print @Cod
       --
       Fetch Next From CurTeste
       Into @Cod
    End
    
    
    Close CurTeste
    Deallocate CurTeste
    
    

     


    Espero que ajude! Luiz Phellipe
    quinta-feira, 19 de janeiro de 2012 22:19
  • Juliana,

    Enquanto o cursor não for fechado ou desalocado da memória, você pode reutilizar em qualquer momento ou movimentação da posição do cursor.

     

    Veja este exemplo:

    CREATE DATABASE TESTE
    
    CREATE TABLE PRODUTOS
    (CODIGO INT IDENTITY(1,1),
     DESCRICAO VARCHAR(100))
    
    INSERT INTO PRODUTOS VALUES ('PRODUTO: '+Convert(Varchar(5),IsNull(@@Identity,1)))
    Go 10000
    
    Select * from Produtos
    
    /************************************************************/
    --CURSOR NEXT--
    CREATE TABLE TESTE
    (CODIGO INT, 
     DESCRICAO VARCHAR(50))
    
    DECLARE @REGISTRO INT,
            @CODIGO INT,
            @DESCRICAO VARCHAR(50)
    
    SET @REGISTRO=0
    
    DECLARE CURSOR_Produtos CURSOR FOR
     SELECT CODIGO, DESCRICAO FROM PRODUTOS
     OPEN Cursor_Produtos
     
     WHILE @REGISTRO <=10
      BEGIN
       FETCH NEXT FROM Cursor_Produtos
       INTO @CODIGO, @DESCRICAO
       
       INSERT INTO TESTE VALUES(@CODIGO, @DESCRICAO)
    
       SET @REGISTRO=@REGISTRO+1 
       
       PRINT 'Código:'+CAST(@CODIGO AS VARCHAR(20))+' Descrição:'+@DESCRICAO
      END
    
     CLOSE Cursor_Produtos
     DEALLOCATE Cursor_Produtos
    
    SELECT * FROM TESTE
    
    /************************************************************/
    -- CURSOR FIRST --
    
    DECLARE @REGISTRO INT,
                    @CODIGO INT,
                    @DESCRICAO VARCHAR(50)
    
    SET @REGISTRO = 0
    
    DECLARE Cursor_Produtos SCROLL CURSOR FOR
     SELECT CODIGO, DESCRICAO FROM PRODUTOS ORDER BY CODIGO ASC
     OPEN Cursor_Produtos
     
     WHILE @REGISTRO = 0
      BEGIN
       FETCH First FROM Cursor_Produtos
       INTO @CODIGO, @DESCRICAO
      
       SET @REGISTRO=@REGISTRO-1 
       
       PRINT 'Código:'+CAST(@CODIGO AS VARCHAR(20))+' Descrição:'+@DESCRICAO
      End
    
     CLOSE Cursor_Produtos
     DEALLOCATE Cursor_Produtos
    
    /************************************************************/
    -- CURSOR LAST --
    
    DECLARE @REGISTRO INT,
                    @CODIGO INT,
                    @DESCRICAO VARCHAR(50)
    
    SET @REGISTRO = 0
    
    DECLARE Cursor_Produtos SCROLL CURSOR FOR
     SELECT CODIGO, DESCRICAO FROM PRODUTOS ORDER BY CODIGO ASC
     OPEN Cursor_Produtos
     
     WHILE @REGISTRO = 0
      BEGIN
       FETCH Last FROM Cursor_Produtos
       INTO @CODIGO, @DESCRICAO
      
       SET @REGISTRO=1
       
       PRINT 'Código:'+CAST(@CODIGO AS VARCHAR(20))+' Descrição:'+@DESCRICAO
      End
    
     CLOSE Cursor_Produtos
     DEALLOCATE Cursor_Produtos
     
    /************************************************************/
    -- CURSOR PRIOR --
    
    DECLARE @REGISTRO INT,
                    @CODIGO INT,
                    @DESCRICAO VARCHAR(50)
    
    SET @REGISTRO = 0
    
    DECLARE Cursor_Produtos SCROLL CURSOR FOR
     SELECT TOP 2 CODIGO, DESCRICAO FROM PRODUTOS ORDER BY CODIGO DESC
     OPEN Cursor_Produtos
     
     WHILE @REGISTRO = 0
      BEGIN
       FETCH LAST FROM Cursor_Produtos
       
       FETCH PRIOR FROM  Cursor_Produtos
       INTO @CODIGO, @DESCRICAO
      
       SET @REGISTRO=1 
       
       PRINT 'Código:'+CAST(@CODIGO AS VARCHAR(20))+' Descrição:'+@DESCRICAO
      End
    
     CLOSE Cursor_Produtos
     DEALLOCATE Cursor_Produtos


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário | MSIT.com]
    domingo, 22 de janeiro de 2012 01:17

Todas as Respostas

  • Juliana

    Isto esta me parecendo meio perigoso... você pode ficar em um loop infinito, fora que a performance de cursores não é boa...

    Vc poderia postar o seu script ou a algo que simule sua necessidade, talvez vc possa evitar o cursor com uma CTE recursiva, um cross apply....


    Att.
    Marcelo Fernandes

    MCP, MCDBA, MCSA, MCTS.
    Se útil, classifique!!!
    Me siga no twitter: @marcelodba

    quinta-feira, 19 de janeiro de 2012 20:42
    Moderador
  • Juliana,

    caso você já tenha plena convicção que irá utilizar mesmo o cursor, segue um exemplo.

    Set Nocount on 
    
    Create Table Teste (Cod int)
    insert into Teste values(1)
    insert into Teste values(2)
    insert into Teste values(3)
    --
    Declare @Cod int
    --
    Declare CurTeste Cursor Scroll
    For   Select   Cod 
          From     Teste
    --
    Open CurTeste
    --
    Fetch Next From CurTeste
    Into @Cod
    --
    While @@FETCH_STATUS = 0
    Begin
       print @Cod
       --
       Fetch Next From CurTeste
       Into @Cod
    End
    --
    -- Retorna para a primeira linha
    --------------------------------------
    Fetch First From CurTeste
    Into @Cod
    
    While @@FETCH_STATUS = 0
    Begin
       print @Cod
       --
       Fetch Next From CurTeste
       Into @Cod
    End
    
    
    Close CurTeste
    Deallocate CurTeste
    
    

     


    Espero que ajude! Luiz Phellipe
    quinta-feira, 19 de janeiro de 2012 22:19
  • Juliana,

    Enquanto o cursor não for fechado ou desalocado da memória, você pode reutilizar em qualquer momento ou movimentação da posição do cursor.

     

    Veja este exemplo:

    CREATE DATABASE TESTE
    
    CREATE TABLE PRODUTOS
    (CODIGO INT IDENTITY(1,1),
     DESCRICAO VARCHAR(100))
    
    INSERT INTO PRODUTOS VALUES ('PRODUTO: '+Convert(Varchar(5),IsNull(@@Identity,1)))
    Go 10000
    
    Select * from Produtos
    
    /************************************************************/
    --CURSOR NEXT--
    CREATE TABLE TESTE
    (CODIGO INT, 
     DESCRICAO VARCHAR(50))
    
    DECLARE @REGISTRO INT,
            @CODIGO INT,
            @DESCRICAO VARCHAR(50)
    
    SET @REGISTRO=0
    
    DECLARE CURSOR_Produtos CURSOR FOR
     SELECT CODIGO, DESCRICAO FROM PRODUTOS
     OPEN Cursor_Produtos
     
     WHILE @REGISTRO <=10
      BEGIN
       FETCH NEXT FROM Cursor_Produtos
       INTO @CODIGO, @DESCRICAO
       
       INSERT INTO TESTE VALUES(@CODIGO, @DESCRICAO)
    
       SET @REGISTRO=@REGISTRO+1 
       
       PRINT 'Código:'+CAST(@CODIGO AS VARCHAR(20))+' Descrição:'+@DESCRICAO
      END
    
     CLOSE Cursor_Produtos
     DEALLOCATE Cursor_Produtos
    
    SELECT * FROM TESTE
    
    /************************************************************/
    -- CURSOR FIRST --
    
    DECLARE @REGISTRO INT,
                    @CODIGO INT,
                    @DESCRICAO VARCHAR(50)
    
    SET @REGISTRO = 0
    
    DECLARE Cursor_Produtos SCROLL CURSOR FOR
     SELECT CODIGO, DESCRICAO FROM PRODUTOS ORDER BY CODIGO ASC
     OPEN Cursor_Produtos
     
     WHILE @REGISTRO = 0
      BEGIN
       FETCH First FROM Cursor_Produtos
       INTO @CODIGO, @DESCRICAO
      
       SET @REGISTRO=@REGISTRO-1 
       
       PRINT 'Código:'+CAST(@CODIGO AS VARCHAR(20))+' Descrição:'+@DESCRICAO
      End
    
     CLOSE Cursor_Produtos
     DEALLOCATE Cursor_Produtos
    
    /************************************************************/
    -- CURSOR LAST --
    
    DECLARE @REGISTRO INT,
                    @CODIGO INT,
                    @DESCRICAO VARCHAR(50)
    
    SET @REGISTRO = 0
    
    DECLARE Cursor_Produtos SCROLL CURSOR FOR
     SELECT CODIGO, DESCRICAO FROM PRODUTOS ORDER BY CODIGO ASC
     OPEN Cursor_Produtos
     
     WHILE @REGISTRO = 0
      BEGIN
       FETCH Last FROM Cursor_Produtos
       INTO @CODIGO, @DESCRICAO
      
       SET @REGISTRO=1
       
       PRINT 'Código:'+CAST(@CODIGO AS VARCHAR(20))+' Descrição:'+@DESCRICAO
      End
    
     CLOSE Cursor_Produtos
     DEALLOCATE Cursor_Produtos
     
    /************************************************************/
    -- CURSOR PRIOR --
    
    DECLARE @REGISTRO INT,
                    @CODIGO INT,
                    @DESCRICAO VARCHAR(50)
    
    SET @REGISTRO = 0
    
    DECLARE Cursor_Produtos SCROLL CURSOR FOR
     SELECT TOP 2 CODIGO, DESCRICAO FROM PRODUTOS ORDER BY CODIGO DESC
     OPEN Cursor_Produtos
     
     WHILE @REGISTRO = 0
      BEGIN
       FETCH LAST FROM Cursor_Produtos
       
       FETCH PRIOR FROM  Cursor_Produtos
       INTO @CODIGO, @DESCRICAO
      
       SET @REGISTRO=1 
       
       PRINT 'Código:'+CAST(@CODIGO AS VARCHAR(20))+' Descrição:'+@DESCRICAO
      End
    
     CLOSE Cursor_Produtos
     DEALLOCATE Cursor_Produtos


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário | MSIT.com]
    domingo, 22 de janeiro de 2012 01:17
  • Oi Luiz,

    Deu o seguinte erro quando tentei usar o fetch first: Fetch First From CurTeste Into @Cod

    Msg 16911, Level 16, State 1, Line 2
    fetch: The fetch type first cannot be used with forward only cursors.

    segunda-feira, 23 de janeiro de 2012 12:17
  • Oi Juliana,

    acho que você esqueceu de colocar a cláusula Scroll após a declaração do cursor. Quando você não especifica nehuma cláusula após a declaração do cursor, ele assume por padrão a condição de Fast_Forward que é otimizado para leituras sequênciais e permite apenas avançar para o próximo registro, e não retroceder.

    Segue link para referência:

    http://msdn.microsoft.com/pt-br/library/ms180169.aspx

     


    Espero que ajude! Luiz Phellipe
    segunda-feira, 23 de janeiro de 2012 22:44
  • Isso mesmo Luiz, muito obrigada!

    bjs

    terça-feira, 24 de janeiro de 2012 11:21