none
bloco begin try não executa rotina RRS feed

  • Pergunta

  • tenho a seguinte estrutura:

    create table #temp
    (
     ind int identity(1,1) primary key,
     campo varchar(100)
    )

    insert into #temp
    (
     campo
    )
    select valor from ##temp_unica where campo = 1

    set @id = 0;

    select @id = id, @campo = campo from #temp where @id > id

    ponto1:
    begin try

     WHILE @@ROWCOUNT > 0
      BEGIN


      --executa processos

      end
    end try

    begin CATCH

     --executa rotina de erro

    end CATCH

    acontece que não está sendo executdo nada o bloco que está entre o begin try e end try. verifiquei também que a rotina não esta com erro.

    tirei o bloco no begin try/end try e begin catch/end catch e roda tudo perfeitamente.

    eu faço esse goto ponto1, porque como leio muitos registros, caso dê problema em algum deles eu gravo numa tabela de log e contiuo o processamento.

    terça-feira, 11 de setembro de 2012 15:28

Respostas

  • na verdade fiz de outra forma. é bem mais rápido e não para o processamento caso ocorram erros. caso seja util o código está abaixo:

    declare
    		@Rows INT,
    		@IdCol INT
     
    create table #temp
    (
     id int identity(1,1) primary key,
     campo varchar(100)
    )
    insert into #temp
    (
     campo
    )
    select campo from tabela
    SET @Rows = 1
    SET @IdCol = 0
    begin try
    	WHILE @Rows > 0
    		begin
    		
    			select top 1
    				@IdCol = id,
    				@campo = campo
    			from
    				#temp
    			where
    				id >= @IdCol
    			order by
    				id
    				
    			sET @Rows = @@ROWCOUNT	
    		
    			--executa processo
    		
    			SET @IdCol += 1
    		end
    end 
    begin CATCH
     --executa rotina de erro
      delete from #temp
       goto ponto1
    end CATCH

    • Marcado como Resposta rafa-martin quarta-feira, 12 de setembro de 2012 13:16
    quarta-feira, 12 de setembro de 2012 00:43

Todas as Respostas

  • Rafa, acredito que o problema esta no WHILE @@ROWCOUNT > 0, quando o begin try inicia o @@rowcount fica como 0, faça o teste e coloque um select @@rowcount antes do WHILE @@ROWCOUNT > 0 e voce verá que retornará 0, sendo que a condição é somente > 0, o bloco de codigo esta correto somente esta condição é que não esta deixando o bloco do codigo acontecer.

    Alexandre Matayosi Conde Mauricio. Se esta sugestão for útil, por favor, classifique-a como útil. Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    terça-feira, 11 de setembro de 2012 15:58
  • Pra resolver isso você pode declarar uma variável inteira e atribuir a ela o @@RowCount, antes do GoTo. E usar esta variável no bloco Try.

    Exemplo:

    Update Top (1) Pessoa Set NmPessoa = NmPessoa
    Declare @LinhasAfetadas int = @@RowCount
    
    goto Ponto1
    
    Print 'C'
    
    ponto1:
    begin try
     WHILE @LinhasAfetadas > 0
      BEGIN
        Print 'A'
      --executa processos
      end
    end try
    begin CATCH
      Print 'B'
     --executa rotina de erro
    end CATCH


    Roberson Ferreira - Database Developer
    Acesse: www.robersonferreira.com.br
    Email: contato@robersonferreira.com.br

    Se esta sugestão for útil, por favor, classifique-a como útil.
    Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    terça-feira, 11 de setembro de 2012 16:38
    Moderador
  • roberson fiz o que você sugeriu... mais parece que fica em loop infinito. pq tá executando o processo, só que a query continua executando.

    declare @cont int

     

    create table #temp
    (
     ind int identity(1,1) primary key,
     campo varchar(100)
    )

    insert into #temp
    (
     campo
    )
    select valor from ##temp_unica where campo = 1

    set @id = 0;

    select @id = id, @campo = campo from #temp where @id > id


    set @cont = @@rowcount

    ponto1:
    begin try

     WHILE @cont > 0
      BEGIN


      --executa processos

      end
    end try

    begin CATCH

     --executa rotina de erro

    end CATCH

    terça-feira, 11 de setembro de 2012 17:03
  • Sim, ficará em loop infinito mesmo, pois a variável @cont recebeu um determinado valor (exemplo, 10) e depois disso nunca mais foi alterada.

    Roberson Ferreira - Database Developer
    Acesse: www.robersonferreira.com.br
    Email: contato@robersonferreira.com.br

    Se esta sugestão for útil, por favor, classifique-a como útil.
    Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    terça-feira, 11 de setembro de 2012 17:21
    Moderador
  • Ou você muda o valor desta variável dentro do While ou você muda o While para um If.

    Exemplo:

    While @cont > 0
    Begin
      ... Seu código
    
      -- Aqui a gnt decrementa a variável. Qdo chegar a zero sairá do While
      Set @cont = @cont - 1
    End
    

    Com If:

    If @cont > 0
    Begin
      ... Seu código
    End



    Roberson Ferreira - Database Developer
    Acesse: www.robersonferreira.com.br
    Email: contato@robersonferreira.com.br

    Se esta sugestão for útil, por favor, classifique-a como útil.
    Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    terça-feira, 11 de setembro de 2012 17:24
    Moderador
  • então eu vi que era isso. só que ela não deveria assumir o papel do @@rowcount já que foi atribuida o valor da mesma? porque o valor do @@rowcount também nunca irá mudar.

    até porque a minha variável @cont sempre terá o valor igual 1, já que eu sempre pego 1 registro (e assim procesando as outras linhas)

    ah uma coisa!!! o problema que se eu decrementar vai exeuctar apenas uma vez meu bloco dentro do while. porque a variável @cont sempre será 1. veja que faço p select top 1. dessa forma é mais ráppido ler todos os registros.

    e como faria agora para ler todos os registros e sair do while quando terminar de ler.

    quando uso @@rowcount sem o bloco begin try e begin catch processa todas as linhas que tenho sem problemas. e assim que termina de ler as linhas, sai do while.

    • Editado rafa-martin terça-feira, 11 de setembro de 2012 17:32 r
    terça-feira, 11 de setembro de 2012 17:27
  • Ela não assume o papel do @@RowCount: ela assume o valor do @@RowCount.

    E o @@RowCount vai mudar dependendo da sintaxe que está no While. Se no While tiver um Update ou um Delete, @@RowCount irá mudar. Diferentemente do conteúdo da @cont, que só mudará se você alterar explicitamente.

    Talvez você não precise de nada disso: a questão é: o que você quer fazer dentro do Try/Catch?

    Por que você entende que precisa recuperar o @@RowCount pra fazer alguma coisa no Try/Catch?


    Roberson Ferreira - Database Developer
    Acesse: www.robersonferreira.com.br
    Email: contato@robersonferreira.com.br

    Se esta sugestão for útil, por favor, classifique-a como útil.
    Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    terça-feira, 11 de setembro de 2012 17:33
    Moderador
  • veja meu código completo:

    declare @cont int
     
    create table #temp
    (
     ind int identity(1,1) primary key,
     campo varchar(100)
    )
    insert into #temp
    (
     campo
    )
    select valor from ##temp_unica where campo = 1
    set @id = 0;
    select @id = id, @campo = campo from #temp where @id > id
    set @cont = @@rowcount
    ponto1:
    begin try
     WHILE @cont > 0
      BEGIN
      --executa processos
       select @id = id, @campo = campo from #temp where @id > id
      end
    end try
    begin CATCH
     --executa rotina de erro
      delete from #temp
       goto ponto1
    end CATCH

    na verdade meu while estava de outra forma, com o bloco begin try. acontece que vi que dava para melhorar a performance desse bloco (e realmente dá). coloquei esse bloco do begin try porque, caso ocorra algum erro durante a leitura das linhas (dentro do while), no bloco begin catch faço o tratamento do erro e volto para o bloco do while (veja que no begin catch tenho um goto ponto1). e assim vou lendo as linhas.

    nesse while que mostrei é bem mais rápido o processamento das linhas (consideravelmente). o problema é que preciso gravar as linhas que irão dar problemas sem para o processamento. ou seja, processa tudo e as linhas com problema eu jogo num log (exatamente como eu estava fazendo).

    tem alguma outra idéia de como posso fazer essa rotina (de guardar as linhas com erros e continuar o lendo as outras sem para o processamento)?

    terça-feira, 11 de setembro de 2012 17:41
  • Não estou conseguindo entender o objetivo do seu código.

    Exemplo:

    Dentro do While você tem: 

    select @id = id, @campo = campo from #temp where @id > id

    Você joga os campos para algumas variáveis, mas depois não faz nada com elas.

    Me explica o porque do While. O que você quer selecionar na tabela?


    Roberson Ferreira - Database Developer
    Acesse: www.robersonferreira.com.br
    Email: contato@robersonferreira.com.br

    Se esta sugestão for útil, por favor, classifique-a como útil.
    Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    terça-feira, 11 de setembro de 2012 18:02
    Moderador
  • na verdade eu uso sim. as variáveis, uso em inserts e updates que tem dentro no meu while.

    o que preciso é processar todas as linhas. caso de algum erro eu jogo as mesmas num log e continuo o processamento. Ou seja, não pode parar o processamento se durante essa leitura ocorrem erros. por isso tinha feito o begin try. só que com esse while que postei não está sendo possível.

    entendeu?

    terça-feira, 11 de setembro de 2012 18:10
  • Entendi.

    Mas o que você considera como erro? O que seria, na prática, um erro?


    Roberson Ferreira - Database Developer
    Acesse: www.robersonferreira.com.br
    Email: contato@robersonferreira.com.br

    Se esta sugestão for útil, por favor, classifique-a como útil.
    Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    terça-feira, 11 de setembro de 2012 18:49
    Moderador
  • na verdade fiz de outra forma. é bem mais rápido e não para o processamento caso ocorram erros. caso seja util o código está abaixo:

    declare
    		@Rows INT,
    		@IdCol INT
     
    create table #temp
    (
     id int identity(1,1) primary key,
     campo varchar(100)
    )
    insert into #temp
    (
     campo
    )
    select campo from tabela
    SET @Rows = 1
    SET @IdCol = 0
    begin try
    	WHILE @Rows > 0
    		begin
    		
    			select top 1
    				@IdCol = id,
    				@campo = campo
    			from
    				#temp
    			where
    				id >= @IdCol
    			order by
    				id
    				
    			sET @Rows = @@ROWCOUNT	
    		
    			--executa processo
    		
    			SET @IdCol += 1
    		end
    end 
    begin CATCH
     --executa rotina de erro
      delete from #temp
       goto ponto1
    end CATCH

    • Marcado como Resposta rafa-martin quarta-feira, 12 de setembro de 2012 13:16
    quarta-feira, 12 de setembro de 2012 00:43
  • Rafa, favor classificar as respostas.

    Roberson Ferreira - Database Developer
    Acesse: www.robersonferreira.com.br
    Email: contato@robersonferreira.com.br

    Se esta sugestão for útil, por favor, classifique-a como útil.
    Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    quarta-feira, 12 de setembro de 2012 10:48
    Moderador