Procedure Recursiva com erro de cursor já aberto

Dúvidas, dicas e truques de PL/SQL. Aqui também vão assuntos relacionados a pacotes, triggers, funções, Java-Stored Procedures, etc
Responder
vindalencio
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 140
Registrado em: Qui, 16 Fev 2006 9:42 am
Localização: Curitiba
Vanderlei Indalencio

Caros amigos, estou com problemas na rcursividade desta procedure,
mostra erro

Selecionar tudo

 "ora-06511 pl sql cursor already open"
Se alguém puder me ajudar, agradeço..

Selecionar tudo

Procedure calculo_main(P_INI VARCHAR, P_FIM VARCHAR) IS
   FLAG VARCHAR2(1):= 'N'; 
   AUX1 NUMBER := 1;
   BEGIN
      OPEN PRINCIPAL(P_INI,P_FIM);
      LOOP
          FETCH PRINCIPAL INTO P_PROD_ACABADO;
          EXIT WHEN PRINCIPAL%NOTFOUND;
          OPEN SUBPRINCIPAL(P_PROD_ACABADO,P_PROD_ACABADO);
          LOOP
		EXIT WHEN SUBPRINCIPAL%NOTFOUND;
		FETCH SUBPRINCIPAL INTO      P_PROD_ACABADO,P_SUB_MP,P_DESCRIPTION,P_COMPONENT_QUANTITY,P_ITEM_TYPE;
          IF CONDICAO
	  	"FAZ CALCULOS"
	  ELSE
	     calculo_main(P_PROD_ACABADO, P_PROD_ACABADO);
	  END IF;
      END LOOP;
      CLOSE SUBPRINCIPAL; 
      END LOOP;
      CLOSE PRINCIPAL;
   END; 

Att :?
SergioLBJr
Rank: Oracle Guru
Rank: Oracle Guru
Mensagens: 448
Registrado em: Ter, 16 Jun 2009 3:07 pm
Localização: Parobé - RS
Sérgio Luiz Bonemberger Junior
Programador Junior
Parobé RS

[]s

Cara a única coisa estranha q pude reparar no seu código foi
o EXIT WHEN antes do fetch.

troque essas linhas de posição:

Selecionar tudo

EXIT WHEN SUBPRINCIPAL%NOTFOUND; 
FETCH SUBPRINCIPAL INTO P_PROD_ACABADO,P_SUB_MP,P_DESCRIPTION,P_COMPONENT_QUANTITY,P_ITEM_TYPE; 
gfkauer
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 389
Registrado em: Ter, 27 Jul 2010 1:34 pm
Localização: Sapiranga - RS
Contato:
Quem falou que programar era fácil??

Quanto mais dificil for a implementação mais valorizado seu trabalho será!

Acessem: www.gfkauer.com.br

Faz um teste,

Inverte a linha do exit subprincipal e do fetch do mesmo.
vindalencio
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 140
Registrado em: Qui, 16 Fev 2006 9:42 am
Localização: Curitiba
Vanderlei Indalencio

NÂO, amigo...
Não teve nenhum efeito!!!

:(
Diego_Mello
Rank: DBA Júnior
Rank: DBA Júnior
Mensagens: 229
Registrado em: Sex, 05 Set 2008 2:59 pm
Localização: Igrejinha - RS
Diego Mello
Igrejinha - RS
www.twitter.com/diegolmello

Te dá erro porque na chamada da procedure na segunda vez o cursor já está aberto.
Tenta fazer com FOR ao invés de CURSOR.
vindalencio
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 140
Registrado em: Qui, 16 Fev 2006 9:42 am
Localização: Curitiba
Vanderlei Indalencio

Caro Diego_mello, o problema não é esse...
Pois em procedure recursiva... eu preciso usar cursores Explicitos, com OPEN FETCH e CLOSE, o FOR já da erro de cara, por ser Cusros IMPLICITO..

Att
gfkauer
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 389
Registrado em: Ter, 27 Jul 2010 1:34 pm
Localização: Sapiranga - RS
Contato:
Quem falou que programar era fácil??

Quanto mais dificil for a implementação mais valorizado seu trabalho será!

Acessem: www.gfkauer.com.br

Cara, indiferente ao erro que tu esta obtendo, já notou que dependendo como for sua estrutura de dados você podera entrar em loop infinito?
Se importaria em explicar qual seu objetivo, quem sabe assim possamos sugerir algo diferente.
Estou com algumas idéias aqui, tipo usar tabelas de memória, mas para saber qual se adequaria melhor precisaria saber do objetivo...
burga
Rank: DBA Pleno
Rank: DBA Pleno
Mensagens: 232
Registrado em: Qui, 26 Nov 2009 1:05 pm
Localização: SP
Ricardo H. Tajiri

Pelo que eu estou vendo, o P_PROD_ACABADO é do tipo VARCHAR, então os cursores não retornam uma lista...

Então não vejo porquê não fechar o cursor logo após dar o FETCH. E também não estou entendendo a importância do LOOP aí no seu código...


Só se você omitiu alguma coisa importante, mas do jeito que está aí, poderia ser feito:

Selecionar tudo

Procedure calculo_main(P_INI VARCHAR, P_FIM VARCHAR) IS
  FLAG VARCHAR2(1):= 'N';
  AUX1 NUMBER := 1;
BEGIN
  OPEN PRINCIPAL(P_INI,P_FIM);
  FETCH PRINCIPAL INTO P_PROD_ACABADO;
  CLOSE PRINCIPAL;
  IF (P_PROD_ACABADO IS NOT NULL) THEN
    OPEN SUBPRINCIPAL(P_PROD_ACABADO,P_PROD_ACABADO);
    FETCH SUBPRINCIPAL INTO P_PROD_ACABADO,P_SUB_MP,P_DESCRIPTION,P_COMPONENT_QUANTITY,P_ITEM_TYPE;
    CLOSE SUBPRINCIPAL;
    IF (P_PROD_ACABADO IS NOT NULL) THEN
      IF CONDICAO THEN
        "FAZ CALCULOS";
      ELSE
        calculo_main(P_PROD_ACABADO, P_PROD_ACABADO);
      END IF;
    END IF;
  END IF;
END; 
SergioLBJr
Rank: Oracle Guru
Rank: Oracle Guru
Mensagens: 448
Registrado em: Ter, 16 Jun 2009 3:07 pm
Localização: Parobé - RS
Sérgio Luiz Bonemberger Junior
Programador Junior
Parobé RS

[]s

Cara neste teu trecho de código não tem onde estourar o erro que tu postou.

Ou ele ta nas partes que tu omitiu, ou ta na chamada de alguma outra procedure tipo essa "calculo_main".
gfkauer
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 389
Registrado em: Ter, 27 Jul 2010 1:34 pm
Localização: Sapiranga - RS
Contato:
Quem falou que programar era fácil??

Quanto mais dificil for a implementação mais valorizado seu trabalho será!

Acessem: www.gfkauer.com.br

Pois é burga, pelo código original eu havia imaginado que na primeira chamada os parametros p_ini e p_fim são diferentes gerando um array de resultados desta forma até faria sentido este loop.
O que eu não entendi é o porque chamar a procedure novamente para os dados obtidos no cursor SUBPRINCIPAL. Eles viriam a ser diferentes do prod acabado principal será?

Bom a nós resta esperar um esclarecimento dos objetivos do procedimento para então sugestionar algo mais pontual...
gfkauer
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 389
Registrado em: Ter, 27 Jul 2010 1:34 pm
Localização: Sapiranga - RS
Contato:
Quem falou que programar era fácil??

Quanto mais dificil for a implementação mais valorizado seu trabalho será!

Acessem: www.gfkauer.com.br

SergioLBJr, o que ta estourando o erro é chamar a procedure dentro dela mesmo. Quando ele faz a chamada dentro do If ele ainda não resolvou todo o cursor da primeira chamada e tenta abri-lo novamente. Neste momento estoura o erro. Agora eu não entendo qual o objetivo desta recursividade...
SergioLBJr
Rank: Oracle Guru
Rank: Oracle Guru
Mensagens: 448
Registrado em: Ter, 16 Jun 2009 3:07 pm
Localização: Parobé - RS
Sérgio Luiz Bonemberger Junior
Programador Junior
Parobé RS

[]s

Opa, agora que percebi a parte da recursividade :oops:

Cara onde ta declarado o teu cursor ??

A unica coisa que conseguo imaginar que possa estar acontecendo é que na tua segunda chamada da procedure ele ta tentando fzer o OPEN e enchergando que o cursor esta aberto (mesmo que seja na primeira chamada).
burga
Rank: DBA Pleno
Rank: DBA Pleno
Mensagens: 232
Registrado em: Qui, 26 Nov 2009 1:05 pm
Localização: SP
Ricardo H. Tajiri

Pois é burga, pelo código original eu havia imaginado que na primeira chamada os parametros p_ini e p_fim são diferentes gerando um array de resultados desta forma até faria sentido este loop.
Então, pelo código, eu acredito que não gere um array de resultados, senão de duas uma, ou o FECTH retornaria uma exceção (considerando P_PROD_ACABADO como do tipo VARCHAR), ou a chamada na recursão daria exeção (considerando P_PROD_ACABADO como um array), pois o tipo do parâmetro do procedimento não é um array.


Agora que eu vi sua assinatura... kkkkkkkk[/code]
vindalencio
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 140
Registrado em: Qui, 16 Fev 2006 9:42 am
Localização: Curitiba
Vanderlei Indalencio

Caros Amigos, Quando passo o o P_INI e P_FIM, o primeiro Loop me retorna uma lista de componetes... P_PROD_ACABADO
No segundo LOOP, eu passo cada Componente, para que retorne os SUB_COMPONETES... caso retorne uma peça Ele Calcula na condição "Faz calculos", Se não retornar peça e sim retornar componente ele precisa vafer a recursividade até chegar numa peça pra CALCULO,
é por isso que não vai entrar em LOOP enfinito, porque no final é sempre uma peça.
O Meus Cursores estou declarando dentro da PACKEGE.

Agora não sei o que pode estar dando erro, pois fiz teste, e ele estoura quando faz a segunda chamada da calculo_main.
Diego_Mello
Rank: DBA Júnior
Rank: DBA Júnior
Mensagens: 229
Registrado em: Sex, 05 Set 2008 2:59 pm
Localização: Igrejinha - RS
Diego Mello
Igrejinha - RS
www.twitter.com/diegolmello

Como não conheço tua estrutura, não sei te dizer exatamente o que tu podes fazer, então só posso te dar uma vaga ideia :D

Vê se te ajuda:

Selecionar tudo

SQL> SELECT pai
  2        ,filho
  3  		,peca
  4  		,DECODE(peca, 'S', 'CALCULA!') calculo
  5    FROM (
  6  --/ Sua tabela recursiva...
  7  SELECT 1 pai, 2 filho, 'N' peca FROM dual UNION
  8  SELECT 2 pai, 3 filho, 'N' peca FROM dual UNION
  9  SELECT 3 pai, 4 filho, 'N' peca FROM dual UNION
 10  SELECT 4 pai, 5 filho, 'S' peca FROM dual
 11         )
 12  CONNECT BY PRIOR filho = pai
 13  START WITH pai = 1;
 
       PAI      FILHO PECA CALCULO
---------- ---------- ---- --------
         1          2 N    
         2          3 N    
         3          4 N    
         4          5 S    CALCULA!
SergioLBJr
Rank: Oracle Guru
Rank: Oracle Guru
Mensagens: 448
Registrado em: Ter, 16 Jun 2009 3:07 pm
Localização: Parobé - RS
Sérgio Luiz Bonemberger Junior
Programador Junior
Parobé RS

[]s

Cara, tenta declarar os teus cursores na procedure.
vindalencio
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 140
Registrado em: Qui, 16 Fev 2006 9:42 am
Localização: Curitiba
Vanderlei Indalencio

MEU DEUS....quantas tentativas....
estava a 2 dias nisso....
POR INCRIVEL QUE PAREÇA, a dica do nosso amigo SergioLBJr de criar o cursor dentro da PROCEDURE...

SIMPLISMETE isso...

Valeu Pessoal...
RESOLVIDO....

TENHO QUE FAZER OS CURSORES LOCAIS...
SergioLBJr
Rank: Oracle Guru
Rank: Oracle Guru
Mensagens: 448
Registrado em: Ter, 16 Jun 2009 3:07 pm
Localização: Parobé - RS
Sérgio Luiz Bonemberger Junior
Programador Junior
Parobé RS

[]s

Eu tive muito pouco contato com recursividade, mas sempre que utilizei declarei os cursores dentro das procedures, por isso nunca me deparei com esse tipo de erro.

Mas se fomos parar pra pensar isso é bem lógico, uma vez que o cursor for declarado de novo ele deve ser considerado com um novo cursor, e como o seu estava na package ele era considerado como sendo o mesmo.
E o no seu procedimento você não podia fechalo pois chamava a procedure recursiva no meio do loop, logo acusava que ainda estava aberto.
vindalencio
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 140
Registrado em: Qui, 16 Fev 2006 9:42 am
Localização: Curitiba
Vanderlei Indalencio

É isso ai amigo SergioLBJr, pois eu já tinha criado recursividade somente em procedures... nunca em PACKEGES, com isso aprendemos mais uma...

Abraços a todos que contribuiram
Responder
  • Informação