At end of table

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
fbarros300472
Rank: Analista Júnior
Rank: Analista Júnior
Mensagens: 73
Registrado em: Qui, 21 Set 2006 10:13 am
Localização: sp

Boa tarde !

A executar uma trigger recebo a mensagem at end of table. Ela se dá em função de um select que numa determinada situação não traz resultado algum. Gostaria de saber se tem como tratar essa mensagem de forma que não impeça a excecução do resto da trigger.

Obrigado.
Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5026
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered

Como assim?
Você faz um select dentro de uma trigger de banco?
Explica melhor o que você está fazendo pra gente entender!!! :-o
fbarros300472
Rank: Analista Júnior
Rank: Analista Júnior
Mensagens: 73
Registrado em: Qui, 21 Set 2006 10:13 am
Localização: sp

A trigger é a seguinte (a parte em vermelho é que eu estou com problema):

Selecionar tudo

create or replace trigger teste
  before insert on TITMMOVCOMPL
  for each row
declare
  OST TITMMOVCOMPL.OS%type;
  TP CHAR;
  DTOS DATE ;
  I VARCHAR2(15);
  preço TPRD.PRECO1%TYPE;
  QTDE TITMMOV.QUANTIDADE%TYPE;
  CODIGO TPRD.CODIGOPRD%TYPE;
  TPMOV TMOV.CODTMV%TYPE;
  
begin
  
    
  SELECT CODTMV INTO TPMOV
    FROM TMOV
    WHERE IDMOV=:NEW.IDMOV;
    
    IF TPMOV='1.1.04' AND :NEW.OS IS NOT NULL THEN
  
  
  
  IF :NEW.OS IS NOT NULL THEN  
  
     SELECT NR_ORDSERV into OST 
     FROM HISTMANU@GUB
     WHERE NR_ORDSERV=:NEW.OS;
  
     SELECT TP_MANUT INTO TP
     FROM HISTMANU@GUB
     WHERE NR_ORDSERV=:NEW.OS;
  
     SELECT DH_SAIDA INTO DTOS 
     FROM HISTMANU@GUB
     WHERE NR_ORDSERV=:NEW.OS;
     
     SELECT TPRD.CODIGOPRD INTO CODIGO
     FROM TPRD,TITMMOV 
     WHERE TPRD.IDPRD=TITMMOV.IDPRD
           AND TITMMOV.IDMOV=:NEW.IDMOV
           AND TITMMOV.NSEQITMMOV=:NEW.NSEQITMMOV;
           
     SELECT CD_PECA INTO I FROM HISTPECA@GUB              -------------------- H E R E ! ! !--------------------
     WHERE NR_ORDSERV=TO_NUMBER(:NEW.OS,'9999999999')     -------------------- H E R E ! ! !--------------------
           AND CD_PECA=CODIGO;                            -------------------- H E R E ! ! !--------------------
  
     IF OST IS NOT NULL AND DTOS IS NOT NULL THEN
           RAISE_APPLICATION_ERROR (-20001,'OS Nº '||:NEW.OS||' ESTÁ FECHADA !!!');
  
           ELSIF OST IS NOT NULL THEN
           SELECT TPRD.CODIGOPRD, TITMMOV.QUANTIDADE,TPRD.PRECO1 INTO CODIGO, QTDE,preço
           FROM TPRD,TITMMOV 
           WHERE TPRD.IDPRD=TITMMOV.IDPRD
                 AND TITMMOV.IDMOV=:NEW.IDMOV
                 AND TITMMOV.NSEQITMMOV=:NEW.NSEQITMMOV;
           IF I<>CODIGO THEN  
                       INSERT INTO HISTPECA@GUB (NR_ORDSERV,CD_PECA,QT_PECA,CD_EMPRESA,CD_PECA_CO,
                         NR_SER,TP_CTRL,CD_EMP_USU,CD_USUARIO,DH_ULT_ATZ,NR_REQ,VL_CUSTO,DT_UTILIZA)
                       VALUES (:NEW.OS,CODIGO,QTDE,1,'VAZIO','U',TP,1,1,SYSDATE,:NEW.OS,preço,SYSDATE);
          ELSE 
                 UPDATE HISTPECA@GUB
                 SET QT_PECA=(QT_PECA + QTDE),DH_ULT_ATZ=SYSDATE,DT_UTILIZA=SYSDATE
                 WHERE NR_ORDSERV=TO_NUMBER(:NEW.OS,'9999999999')
                       AND CD_PECA=CODIGO; 
            END IF;
           
    
    
       ELSIF OST IS NULL AND :NEW.OS IS NOT NULL THEN
              RAISE_APPLICATION_ERROR (-20001,'OS INEXISTENTE !!!'); 
            
            END IF;
    END IF;
    END IF;
     
end teste;
gokden
Rank: DBA Pleno
Rank: DBA Pleno
Mensagens: 264
Registrado em: Dom, 19 Ago 2007 8:18 pm
Localização: Ribeirão Preto - SP
Lucas de Souza

OCA Developer
Analista de sistemas

olha cara... eu vo ti falar uma super dica que um amigo meu (OCP Developer) sempre me falava =D

quando você for fazer triggers, packages ou até no forms....
em todo select qui você for fazer, sempre separe eles com BEGIN...EXCEPTION...END desse modo, você pode tratar cada erro de cada select separadamente... ou intao crie uma variavel numérica vn_erro, que a cada passo qui o seu script anda, ele recebe uma valor diferente, e nos exceptions mostre esse valor, para você saber onde está o erro

=D
fbarros300472
Rank: Analista Júnior
Rank: Analista Júnior
Mensagens: 73
Registrado em: Qui, 21 Set 2006 10:13 am
Localização: sp

Lucas, será que você podia exemplificar as duas situações para mim. Sou iniciante. Desde já, obrigado pela atenção.
gokden
Rank: DBA Pleno
Rank: DBA Pleno
Mensagens: 264
Registrado em: Dom, 19 Ago 2007 8:18 pm
Localização: Ribeirão Preto - SP
Lucas de Souza

OCA Developer
Analista de sistemas

então, seria meio assim:

Selecionar tudo

create or replace trigger teste
before insert on TITMMOVCOMPL
for each row

DECLARE
   OST TITMMOVCOMPL.OS%type;
   TP CHAR;
   DTOS DATE ;
   I VARCHAR2(15);
   preço TPRD.PRECO1%TYPE;
   QTDE TITMMOV.QUANTIDADE%TYPE;
   CODIGO TPRD.CODIGOPRD%TYPE;
   TPMOV TMOV.CODTMV%TYPE;

BEGIN

   SELECT CODTMV INTO TPMOV
     FROM TMOV
    WHERE IDMOV=:NEW.IDMOV;

   IF TPMOV='1.1.04' AND :NEW.OS IS NOT NULL THEN   -- Aqui você já faiz um "IF :NEW.OS IS NOT NULL", não precisa repeti-lo
--      IF :NEW.OS IS NOT NULL THEN
      BEGIN
         SELECT NR_ORDSERV into OST
           FROM HISTMANU@GUB
          WHERE NR_ORDSERV=:NEW.OS;
      EXCEPTION
         when no_data_found then
            RAISE_APPLICATION_ERROR(-20001, 'não encontrado');
         when others then
            RAISE_APPLICATION_ERROR(-20001, 'erro: '||sqlerrm);
      END;

      BEGIN
         SELECT TP_MANUT INTO TP
           FROM HISTMANU@GUB
          WHERE NR_ORDSERV=:NEW.OS;
      EXCEPTION
         when no_data_found then
            RAISE_APPLICATION_ERROR(-20001, 'não encontrado');
         when others then
            RAISE_APPLICATION_ERROR(-20001, 'erro: '||sqlerrm);
      END;

      BEGIN
         SELECT DH_SAIDA INTO DTOS
           FROM HISTMANU@GUB
          WHERE NR_ORDSERV=:NEW.OS;
      EXCEPTION
         when no_data_found then
            RAISE_APPLICATION_ERROR(-20001, 'não encontrado');
         when others then
            RAISE_APPLICATION_ERROR(-20001, 'erro: '||sqlerrm);
      END;
.......
mais ai depende também da sua regra de negocio, as vezes não dá pra você fazer isso em todos os selects, e existem varios outros tipos exeptions, e você pode colocar uma ação NULL em um exception
um outro modo seria assim também... mais ai é mais para rastrear erros...

Selecionar tudo

create or replace trigger teste
before insert on TITMMOVCOMPL
for each row

DECLARE
   OST TITMMOVCOMPL.OS%type;
   TP CHAR;
   DTOS DATE ;
   I VARCHAR2(15);
   preço TPRD.PRECO1%TYPE;
   QTDE TITMMOV.QUANTIDADE%TYPE;
   CODIGO TPRD.CODIGOPRD%TYPE;
   TPMOV TMOV.CODTMV%TYPE;

BEGIN

   SELECT CODTMV INTO TPMOV
     FROM TMOV
    WHERE IDMOV=:NEW.IDMOV;

   IF TPMOV='1.1.04' AND :NEW.OS IS NOT NULL THEN   -- Aqui você já faiz um "IF :NEW.OS IS NOT NULL", não precisa repeti-lo
--      IF :NEW.OS IS NOT NULL THEN
      vn_erro := 0;
      SELECT NR_ORDSERV into OST
        FROM HISTMANU@GUB
       WHERE NR_ORDSERV=:NEW.OS;

      vn_erro := 1;
      SELECT TP_MANUT INTO TP
        FROM HISTMANU@GUB
       WHERE NR_ORDSERV=:NEW.OS;

      vn_erro := 2;
      SELECT DH_SAIDA INTO DTOS
        FROM HISTMANU@GUB
       WHERE NR_ORDSERV=:NEW.OS;

   END IF;

EXCEPTION
   when others then
      RAISE_APPLICATION_ERROR(-20001, '('||vn_erro||')Erro: '||sqlerrm);
end teste;
assim você vai poder saber onde qui aconteceu o erro também....
mais não vai poder trata-lo iguai no primeiro exemplo
fbarros300472
Rank: Analista Júnior
Rank: Analista Júnior
Mensagens: 73
Registrado em: Qui, 21 Set 2006 10:13 am
Localização: sp

Boa tarde Lucas, tudo bem ?

Acho que talvez eu não esteja me fazendo entender.
O problema que estou tendo está no select em vermelho. Na maioria das vezes ele não irá retornar valor algum. Em função disso, a execução da trigger é interrompida quando isto ocorre. Queria saber se tem como tratar isso de forma que continue a executar o resto da trigger.....
Muito obrigado pela sua atenção.
ricardorauber
Rank: Analista Júnior
Rank: Analista Júnior
Mensagens: 96
Registrado em: Qua, 21 Jun 2006 11:33 pm
Localização: Canoas RS

Selecionar tudo

BEGIN
  SELECT CD_PECA INTO I FROM HISTPECA@GUB 
  WHERE NR_ORDSERV=TO_NUMBER(:NEW.OS,'9999999999') 
  AND CD_PECA=CODIGO; 
EXCEPTION
  WHEN OTHERS THEN
    NULL;
END;
ricardorauber
Rank: Analista Júnior
Rank: Analista Júnior
Mensagens: 96
Registrado em: Qua, 21 Jun 2006 11:33 pm
Localização: Canoas RS

Só para avisar, comandos SELECT INTO muitas vezes geram problemas que demoram horas para se descobrir como resolver, por isso vai a dica: use SEMPRE cursores!

:-o
gokden
Rank: DBA Pleno
Rank: DBA Pleno
Mensagens: 264
Registrado em: Dom, 19 Ago 2007 8:18 pm
Localização: Ribeirão Preto - SP
Lucas de Souza

OCA Developer
Analista de sistemas

mais usar cursores não piora a performace do comando inteiro ?
até onde eu sei quando você usa um cursor a cada linha do cursor ele faiz um parse a mais no banco, então dependendo do seu select, ele ficaria mais lento que no caso do INTO....
eu uso o cursor quando eu preciso de mais de um valor retornado do select.... mais quando se trata de uma linha apenas é muito mais util o uso do SELECT INTO mesmo....
fbarros300472
Rank: Analista Júnior
Rank: Analista Júnior
Mensagens: 73
Registrado em: Qui, 21 Set 2006 10:13 am
Localização: sp

Gente, valeu mesmo. Muito obrigado. Vocês me quebraram um galhão.
ricardorauber
Rank: Analista Júnior
Rank: Analista Júnior
Mensagens: 96
Registrado em: Qua, 21 Jun 2006 11:33 pm
Localização: Canoas RS

mais usar cursores não piora a performace do comando inteiro ?
Segundo uma colega dba minha, o oracle internamente cria um cursor para qualquer tipo de consulta então quando tu usa cursores, poupa esse trabalho pro banco e garante controle no teu código, logo, é a melhor prática.
Responder
  • Informação
  • Quem está online

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