Cursor com clausula where dinamica

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
marlonpasquali
Rank: DBA Pleno
Rank: DBA Pleno
Mensagens: 248
Registrado em: Sex, 06 Fev 2009 3:02 pm
Localização: ERECHIM - RS

Olá pessoal, preciso de um help por favor
Tenho um cursor e preciso criar uma clausula where que seja dinamica conforme a necessidade dos parametros enviados conforme exemplo abaixo:

Selecionar tudo

cursor c_Ordens is 
select gbh.Batch_id         OrdemId
      ,gbh.batch_no         Ordem
      ,frh.routing_no       Roteiro
      ,mc.segment1          Classe
      ,mc.description       DescClasse
      ,to_char(gbh.plan_start_date,'dd/mm/yy hh24:mi:ss')  Data_inicio_Planej
from 
       gme_batch_header      gbh
      ,ic_item_mst           iim
      ,mtl_system_items_b    msi
      ,gme_material_details  gme
      ,FM_rout_hdr           frh
      ,mtl_item_categories   mic
      ,mtl_category_sets     mcs
      ,mtl_categories        mc
where frh.routing_id    = gbh.routing_id
and   gme.batch_id      = gbh.batch_id
and   gme.item_id       = iim.item_id
and   gme.line_no       = 1 -- indica que é a 1a. linha
and   gme.line_type     = 1 -- indica que é o produto
and   gbh.batch_status  = 2 -- Status Pendente
and   iim.item_no = msi.segment1
and   msi.organization_id   = 104
and   msi.inventory_item_id = mic.inventory_item_id
and   msi.organization_id   = mic.organization_id
and   mic.category_set_id   = mcs.category_set_id
and   mcs.structure_id      = mc.structure_id
and   mic.category_id       = mc.category_id
and   mcs.category_set_name = 'CLASSE DE PLANEJAMENTO'
&p_where
order by 4,6;

begin

if p_Tipo = 1 Then
  p_where := ' and msi.segment1 between '||'80000'||' and '||'99999'||'';
elsif p_Tipo = 2 Then
  p_where := ' and mc.segment1 = '||'SA'||'';  
  p_where := p_where || ' and mc.segment1 = '||'p_Maq1'||';  
elsif p_Tipo = 3 Then
  p_where := ' and mc.segment1 = '||'1AD'||'';  
end if;
  
end;
só que quando vou compilar a rotina dá erro na clausula &p_where.

tem como fazer isso?

obrigado,
Marlon
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

Cursor diretamente não aceita, existem outras possibilidades, uma delas é usa execute imediate.

Agora para saber qual delas é a melhor para vocês apenas conhecendo a aplicação onde será implementado.
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

Eu usaria SYS_REFCURSOR.
Avatar do usuário
fsitja
Rank: OraSauro
Rank: OraSauro
Mensagens: 611
Registrado em: Seg, 19 Jan 2009 4:29 pm
Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html

OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist

Se possível, eu evitaria usar SQL dinâmico, por complicar demais algo que poderia ser mais simples. Principalmente para debugar e detectar erros, fica tudo muito, muito mais complexo e propenso a ter problemas.

Faça a condição IF acima da chamada do cursor: se for tipo 1 então execute o cursor 1, se for tipo 2 então execute o cursor 2, etc.

Se possível, poste a lógica dentro do cursor. Eu arrisco palpitar que dá para resolver sem SQL dinâmico e sem cursor e salvá-lo de vários cabelos brancos e preocupações com performance horrível de cursor for loop.
alexrsilva
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 153
Registrado em: Ter, 27 Mai 2008 1:31 pm
Localização: Rio de Janeiro - RJ
Alex Silva
Analista de Sistemas
11i.10 Applications Developer Implementation Champion
11i.10 E-Business Suite Integration Champion

Como o fistja falou, evite, mas se não puder evitar, aí está uma forma de se fazer um cursor dinâmico

Selecionar tudo

v_curs_sel               varchar2(4000) := null;

    curs_dyncur              reccurtype;
    t_rec                    tb_rec; --type para receber os dados do cursor
    l_curs_sql               long;
v_curs_sel := ' select AAA from xpto where 1=1 ';
--seus if's e concatenações
v_curs_sel := v_curs_sel || ' and 2 = 2 ';

 l_curs_sql := v_curs_sel;

open curs_dyncur for l_curs_sql;
    loop
      fetch curs_dyncur
        into t_rec;
      exit when curs_dyncur%notfound;
  end loop;
  
    close curs_dyncur;
  
Atenciosamente
Rafael Martelli
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 9
Registrado em: Sex, 17 Set 2010 9:58 am
Localização: Araraquara-SP
Rafael Martelli
Analista/Desenvolvedor Oracle
Araraquara-SP

Você pode colocar direto no seu where a condição.
O seu código fica mais limpo, mas o seu select fará uma condição a mais para cada linha. Aí vai da necessidade, mas é uma opção.

Por exemplo:

Selecionar tudo

and     (p_Tipo = 1 and msi.segment1 between 80000 and 99999)
      or (p_Tipo = 2 and mc.segment1 = 'SA'
                           and mc.segment1 = p_Maq1)
      or (p_Tipo = 3 and mc.segment1 = '1AD')
Não testei, mas e só seguir o raciocínio!!
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante