Como resolver o erro ORA-01422

O erro oracle, em código PL-SQL, ORA-01422: exact fetch returns more than request number of rows, é retornado quando em uma única váriavel é tentado retornar mais de um valor, para acertar isso há várias formas dependendo da sua necessidade, vamos a alguns casos:

1 – Query não deve retornar mais de um registro

Vamos a uma situação hipotética, temos uma tabela de pedidos e uma tabela de clientes e queremos pegar um número de pedido dele, para isso usamos a seguinte query:

select id_pedido
into vID_Pedido
from pedido p, cliente c
where c.nome = 'MEISON'
and c.id_cliente = p.id_cliente;

Se o cliente tiver feito somente um pedido, essa query retornará só uma linha, mas se ele já for um cliente que está pedindo pela segunda ou mais vez será retornado mais de uma linha o que retornará o erro em questão, pois tentará jogar para a variavel vID_Pedido mais de um valor, o que não é possível. Para corrigir se a regra permitir é só pegar uma linha, por exemplo o ultimo pedido, ficando dessa forma:

select id_pedido
into vID_Pedido
from pedido p, cliente c
where c.nome = 'MEISON'
and c.id_cliente = p.id_cliente
and rownum=1
order by id_pedido desc;

O rownum=1 restringe a só uma linha, mas lembrando que sem o order by, ele pega a primeira linha que trouxer do banco. O order by irá garantir que seja a ultima linha criada.
2 – Query pode retornar mais de um registro

Tendo como base o primeiro exemplo, porém precisando pegar todos os pedidos desse cliente, o que deve ser feito é tratar cada um deles individualmente, eu utilizaria o loop, ficando assim:

for vAux in (select id_pedido from pedido where id_cliente = 1)
loop
--Procedimento para tratar vAux.id_pedido
end loop;

Dessa forma não é dado o erro ORA-01422 e trata-se da maneira certa cada um dos pedidos.

3 – Query não deve retornar mais de uma linha, erro de cadastro

Isso é causado quando o sistema deveria inserir somente uma linha e por algum erro, inseriu mais de uma, provocando um erro conceitual. É claro que nesse caso deve-se corrigir a origem que é a inserção erronea de mais de uma linha, mas pode-se tratar também no destino, vamos utilizar a mesma query, ela deveria tratar os erros e ficaria dessa forma:

begin
select id_pedido
into vID_pedido
from pedido
where id_cliente = 1;
exception
when too_many_rows then
raise_application_error(-20000,'Erro na tabela pedido, mais linhas para o cliente do que permitido.');
end;

Dessa forma abordamos alguns cenários que podemos sanar esse problema. Caso você tenha algum outro problema, comente poderemos fazer outro artigo para solucionar seu problema.

Related Posts with Thumbnails

Popularity: 8% [?]

You can leave a response, or trackback from your own site.

17 Comments

  • [...] Continue lendo em Meison Almeida Envie para o seu Veja também outros Links de hoje « Concorra Iphone 3gs [...]
    • At 2010.02.20 12:08, Anderson Gomes said:
      Muito bom o post Meison, continua fazendo post com dicas de PL pra gnt ae! ;D

      Abraço!

      • At 2010.02.22 14:11, Meison Almeida said:
        Obrigado, vou tentar ir colocando algumas dicas ai, tendo algum assunto que seja dificil ai, me avise que se eu souber escrevo um artigo sobre ele…

        Abraços

        • At 2010.11.26 17:33, Rejane said:
          MUito BOm Exelente explicação!!!
          • At 2011.01.10 12:51, Pri said:
            Olá preciso colocar em um registro mais de um funcionario. Porem ele da esse erro comentado. COmo devo fazer, estou usando o report. Não consigo de jeito algum.
            • At 2011.01.10 14:34, Meison said:
              Olá,
              Você pode me passar a query que está com dificuldade? Provavelmente você terá que fazer join ao invés de um select onde deve-se trazer somente uma linha. O report eu não sei muitos detalhes, mas se for para colocar duas linhas você faz um join e deixa em um select só, senão você terá que fazer dois selects para trazer os funcionarios.
              • At 2011.01.11 06:14, Pri said:
                function pf_triagemFormula return Char is
                aux varchar2(240);
                begin
                SELECT DISTINCT p.nm_pessoafisica into aux
                from pessoa_fisica p, triagem t
                where p.cd_pessoafisica = t.cd_pftriagem;
                return aux;
                end;

                seria isso ai.

                • At 2011.01.11 06:17, Pri said:
                  lEMBRANDO NÃO É SOMENTE UMA PESSOA FISICA SÃO VARIAS
                  • At 2011.01.11 10:04, Pri said:
                    Já Resolvi, era um simples detalhe no Reports, somente inserir o caminho do campo.
                    • At 2011.01.11 10:44, Pri said:
                      Mais aproveitando, tenho outro problema. Estou com um registro que possuem atualizações. PReciso mostra somente a primeira vez que foi cadastrado. E as atualizações. Isso ta me trazendo varias copias de um mesmo usuario com varias atualizações dele. EX. Um Cliente, quantas, vezes ele fez compras. ATT
                      • At 2011.01.11 15:40, Meison said:
                        Se você precisa mostrar só o usuário uma vez e as atualizações mais de uma vez, vai precisar programar de alguma jeito, do tipo query dentro de query:

                        for v in (select usuario from usuarios)
                        loop
                        dbms_output.put_line(v.usuario);
                        for x in (select atualizacao from usuarios_atualizacao where usuario = v.usuario)
                        loop
                        dbms_output.put_line(x.atualizacao);
                        end loop;
                        end loop;

                        Agora se você quer somente uma quantidade de atualizações pode ser em uma query só tipo:

                        select usuario, (select count(1) from usuarios_atualizacao where usuario=v.usuario) from usuario v;

                        Isso já te ajuda?

                        • At 2011.01.12 06:35, Pri said:
                          Eu preciso que mostre por exemplo smente a primeira vez que o cliente esteve na loja. Query é enorme, tem union.
                          • At 2011.01.12 06:37, Pri said:
                            Esta mostrando assim pra mim.
                            NOme da pessoa e seu dados. CErto, sem repetições
                            Dados de compras. Esta aparecendo: Compra 1, compra 1, compra 1, compra 2, compra 2, compra 2, compra 3, compra 3, compra 3. E as datas estão repetindo. Porem já fiz join.
                            • At 2011.01.12 06:58, Pri said:
                              EU preciso que mostre uma vez cada. Não repetindo. Não sei se deu pra entender.
                              • At 2011.01.12 10:04, Meison said:
                                Consegui entender, provavelmente há alguma coisa faltando no join para trazer por compra, se você puder enviar a query, fica mais fácil de dar uma melhor solução. Porém um jeito que não é o mais ideal mas que resolve (caso TODAS as informações estejam sendo repetidas) é colocar o DISTINCT na frente

                                select distinct campo1, campo2, campo3
                                from ….

                                O distinct te fará trazer só os dados sem repetição.

                                • At 2011.01.13 08:46, Pri said:
                                  QUAL SEU EMAIL, PRA EU MANDAR A QUERY. COM O DISTINCT NÃO DEU CERTO NÃO
                                  • At 2011.01.13 09:21, Pri said:
                                    Olá Meison, falei com um rapaz que esta aqui perto, e me ajudou.
                                    O problema era em uma tabela que não tinha nada haver com sql. Obrigada
                                    (Required)
                                    (Required, will not be published)

                                    Powered by WordPress | Free T-Mobile phones at BestInCellPhones.com. | Thanks to Verizon Wireless, Facebook Games and The diet solution