SQL Error: ORA-01422: a extração exata retorna mais do que

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
danilosantos
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 6
Registrado em: Seg, 07 Set 2009 12:15 am
Localização: São Paulo - SP
Contato:

Olá Galera estou tendo o seguinte problema no oracle:

Selecionar tudo

SQL Error: ORA-01422: a extração exata retorna mais do que o número solicitado de linhas
ORA-06512: em "PROJE.TRG_TAGVALUE_CONTROLE_INS", line 6
ORA-04088: erro durante a execução do gatilho 'PROJE.TRG_TAGVALUE_CONTROLE_INS'
01422. 00000 -  "exact fetch returns more than requested number of rows"
*Cause:    The number specified in exact fetch is less than the rows returned.
*Action:   Rewrite the query or change number of rows requested
Segue código da minha Trigger

Selecionar tudo

create or replace
TRIGGER TRG_TAGVALUE_CONTROLE_INS
AFTER INSERT
ON POC_TAGVALUE
FOR EACH ROW
DECLARE 
ID_CONTR_SEQ NUMBER;
BEGIN
 IF :new.NM_COLUN = 'NM_TAGPA' THEN
    
    SELECT ID_CONTR INTO ID_CONTR_SEQ
    FROM POC_CONTROLE 
    WHERE DT_FINAL IS NULL AND 
          FL_TIPO = 'P' AND 
          NM_TAG  = :new.NM_TAG AND 
          ID_EQUIP = :new.ID_EQUIP AND 
          ID_CENTR = :new.ID_CENTR AND 
          ID_GRUPO = :new.ID_GRUPO;
    
    IF (ID_CONTR_SEQ IS NULL AND :new.VL_TAG = 0) THEN 
      
      -- PEGAR NUMERO SEQUENCE
      SELECT SEQ_ID_CONTR.NEXTVAL INTO ID_CONTR_SEQ FROM dual; 
 
      -- INSERE NOVO CONTROLE    
      INSERT INTO POC_CONTROLE 
      ( ID_CONTR,
        ID_EQUIP,
        ID_CENTR,
        ID_GRUPO,
        DT_INICI,
        FL_TIPO,
        VL_PERDA,
        NM_TAG
      ) VALUES (
        ID_CONTR_SEQ,
        :new.ID_EQUIP,
        :new.ID_CENTR,
        :new.ID_GRUPO,
        :new.DT_TAG_VALUE,
        'P',
        0,
        :new.NM_TAG
      );    

    ELSE
    
      -- ATUALIZA TABELA CONTROLE 
      UPDATE POC_CONTROLE SET DT_FINAL = :new.DT_TAG_VALUE 
      WHERE ID_CONTR = ID_CONTR_SEQ;   
            
    END IF;    
    
 END IF;
 
 IF :new.NM_COLUN = 'NM_TAGPE' THEN 
 
    INSERT INTO POC_CONTROLE 
    ( ID_CONTR,
      ID_EQUIP,
      ID_CENTR,
      ID_GRUPO,
      DT_INICI,
      FL_TIPO,
      VL_PERDA,
      NM_TAG
    ) VALUES (
      ID_CONTR_SEQ,
      :new.ID_EQUIP,
      :new.ID_CENTR,
      :new.ID_GRUPO,
      :new.DT_TAG_VALUE,
      'R',
      :new.VL_TAG,
      :new.NM_TAG
    );    
    
 END IF;

END;
Para testar a Trigger estou executando o seguinte comando:

Selecionar tudo

INSERT INTO TAB_TAGVALUE 
    (ID_EQUIP,
     ID_GRUPO,
     ID_CENTR,
     DT_TAG_INTER,
     DT_TAG_VALUE,
     NM_TAG,
     VL_TAG,
     NM_COLUN
     ) VALUES 
    ('MP09',
     'GR1',
     'WK1',
     SYSDATE,
     SYSDATE,
     'Line1Status',
     1000,
     'NM_TAGPA');
Agradeço desde já .... o que eu faço para resolver este problema galera??????

Danilo
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

Seu select into está retornando mais de uma linha e "estoura" o fetch.

Provavelmente é a query abaixo:

Selecionar tudo

SELECT ID_CONTR INTO ID_CONTR_SEQ
    FROM POC_CONTROLE
    WHERE DT_FINAL IS NULL AND
          FL_TIPO = 'P' AND
          NM_TAG  = :new.NM_TAG AND
          ID_EQUIP = :new.ID_EQUIP AND
          ID_CENTR = :new.ID_CENTR AND
          ID_GRUPO = :new.ID_GRUPO; 
danilosantos
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 6
Registrado em: Seg, 07 Set 2009 12:15 am
Localização: São Paulo - SP
Contato:

Mais como eu faço para resolver este problema?
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

Verifica as tuas querys.

Testa todas elas no banco, e encontre a(s) que retornam mais de uma linha, ao encontra-la verifique se a join esta correta (se não falta nenhum campo na join), se sim então poste no fórum a query problematica, as pk's das tabelas em que ela busca os dados e o resultado desejado do select.
danilosantos
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 6
Registrado em: Seg, 07 Set 2009 12:15 am
Localização: São Paulo - SP
Contato:

Sergio valeu pela ajuda ... mais no inicio do post eu coloquei a mensagem de erro

Selecionar tudo

SQL Error: ORA-01422: a extração exata retorna mais do que o número solicitado de linhas 
ORA-06512: em "PROJE.TRG_TAGVALUE_CONTROLE_INS", line 6 
ORA-04088: erro durante a execução do gatilho 'PROJE.TRG_TAGVALUE_CONTROLE_INS' 
01422. 00000 - "exact fetch returns more than requested number of rows" 
*Cause: The number specified in exact fetch is less than the rows returned. 
*Action: Rewrite the query or change number of rows requested 
O Problema esta no select abaixo

Selecionar tudo

SELECT ID_CONTR INTO ID_CONTR_SEQ 
    FROM POC_CONTROLE 
    WHERE DT_FINAL IS NULL AND 
          FL_TIPO = 'P' AND 
          NM_TAG  = :new.NM_TAG AND 
          ID_EQUIP = :new.ID_EQUIP AND 
          ID_CENTR = :new.ID_CENTR AND 
          ID_GRUPO = :new.ID_GRUPO; 
Gostaria de saber como resolver este problema dentro da Trigger você sabe? Preciso pegar o valor de uma coluna na base de dados usando o SELECT ID_CONTR INTO ID_CONTR_SEQ mais pode ser que exista o registro ou não .....

A Trigger compila corretamente o problema ocorre quando tento inserir qualquer registro sobre a tabela POC_TAGVALUE da o erro citado ácima.

Se alguém soube como me ajudar fico grato galera ....
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

Como a query não tem joins e ela está retornando mais de uma linha, quer dizer que a sua pesquisa está sendo feita com um conjunto de colunas que não possui a primary key.
Olhe para a sua tabela POC_CONTROLE: qual a Primary Key dela? Ela tem alguma Unique Key além da PK, onde você possa pesquisar por chave?
A partir dessa resposta mude a busca para pegar pela PK ou uma UK e o erro não acontecerá.

O critério "where" abaixo retorna mais de uma linha. O motivo só você pode descobrir, ou quem modelou essa tabela. Ou a query está errada ou a tabela está com falha de modelagem, permitindo dados inconsistentes.

Selecionar tudo

DT_FINAL IS NULL AND
          FL_TIPO = 'P' AND
          NM_TAG  = :new.NM_TAG AND
          ID_EQUIP = :new.ID_EQUIP AND
          ID_CENTR = :new.ID_CENTR AND
          ID_GRUPO = :new.ID_GRUPO;
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

Desculpa, sua resposta foi ao mesmo tempo que a minha. :lol:

O problema que o erro está dando foi o que explicamos já, mas não é o único, como você mesmo já descobriu. Se a linha não existir você vai receber um erro ORA-01403 (No Data Found), e você precisa tratá-lo num exception handler no fim do bloco, da forma que seu requisito mandar.
danilosantos
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 6
Registrado em: Seg, 07 Set 2009 12:15 am
Localização: São Paulo - SP
Contato:

Então eu até tentei colocar um Exception na Trigger mais o problema é que se não existir a linha eu quero inserir uma nova na outra tabela entendeu? Tentei fazer isto na trigger e não funcionou ... saberia me dizer como fazer funcionar com a EXCEPTION ?

Valeu pela ajuda .....
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

Sendo bem prático agora, tenta o seguinte (não testei, então dá uma olhada com uma boa pitada de sal, é só uma idéia):

Selecionar tudo

create or replace
TRIGGER TRG_TAGVALUE_CONTROLE_INS
AFTER INSERT
ON POC_TAGVALUE
FOR EACH ROW
DECLARE
ID_CONTR_SEQ NUMBER;
BEGIN
 IF :new.NM_COLUN = 'NM_TAGPA' THEN
     
 -- PEGAR NUMERO SEQUENCE
 SELECT SEQ_ID_CONTR.NEXTVAL INTO ID_CONTR_SEQ FROM dual
  WHERE EXISTS (SELECT 1
                  FROM POC_CONTROLE
                 WHERE DT_FINAL IS NULL AND
                       FL_TIPO = 'P' AND
                       NM_TAG  = :new.NM_TAG AND
                       ID_EQUIP = :new.ID_EQUIP AND
                       ID_CENTR = :new.ID_CENTR AND
                       ID_GRUPO = :new.ID_GRUPO);
  IF (ID_CONTR_SEQ IS NULL AND :new.VL_TAG = 0) THEN
  
  -- INSERT AQUI
danilosantos
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 6
Registrado em: Seg, 07 Set 2009 12:15 am
Localização: São Paulo - SP
Contato:

Valeu por enquanto pela ajudar cara ....

Na tabela POC_CONTROLE a PK é ID_CONTR

É justamente este valor que eu verifico no IF abaixo

Selecionar tudo

SELECT ID_CONTR INTO ID_CONTR_SEQ 
    FROM POC_CONTROLE 
    WHERE DT_FINAL IS NULL AND 
          FL_TIPO = 'P' AND 
          NM_TAG  = :new.NM_TAG AND 
          ID_EQUIP = :new.ID_EQUIP AND 
          ID_CENTR = :new.ID_CENTR AND 
          ID_GRUPO = :new.ID_GRUPO; 

IF (ID_CONTR_SEQ IS NULL AND :new.VL_TAG = 0) THEN 
Se for nulo eu quero inserir uma nova linha na TABELA POC_CONTROLE

Caso contrário eu quero apenas atualizar o valor na tabela POC_CONTROLE com a PK - ID_CONTR no comando abaixo

Selecionar tudo

      -- ATUALIZA TABELA CONTROLE 
      UPDATE POC_CONTROLE SET DT_FINAL = :new.DT_TAG_VALUE 
      WHERE ID_CONTR = ID_CONTR_SEQ; 
Entendeu o que eu quero fazer?

valeu ....
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

Então, quando você for rodar aquele select para obter a PK, ele vai te retornar mais de uma linha. Não vai vir só um valor de ID_CONTR: vai te retornar um conjunto de linhas que satisfazem teu critério de busca (o teu where). Isso vai causar o exception que você está obtendo, você não pode usar um select into.

Não faça isso testando "flag" num IF, é uma prática ruim, deselegante. O negócio vai ser mudar de "select into" para um cursor loop e mexer em todo o conjunto de linhas cujo ID_CONTR seja retornado (cursor loop em si é uma prática ruim, mas isso fica para um outro dia). Lembre-se que como seu select não é por PK, ele vai retornar várias linhas, então ou você vai inserir uma linha ou vai dar update de várias linhas.
danilosantos
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 6
Registrado em: Seg, 07 Set 2009 12:15 am
Localização: São Paulo - SP
Contato:

Então cara .... consegui resolver o problema valeu .... pela ajuda
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 6 visitantes