ORA-01422: exact fetch returns more than requested number of rows

O erro ORA-01422: exact fetch returns more than requested number of rows ocorre quando uma instrução SELECT ... INTO em PL/SQL retorna mais de uma linha. Em PL/SQL, a instrução SELECT ... INTO é usada para buscar um único registro. Se a consulta retornar mais de uma linha, o erro ORA-01422 será gerado.

Como Diagnosticar e Corrigir

1. Verifique a Consulta: Certifique-se de que a consulta usada com SELECT … INTO está estruturada para retornar exatamente uma linha. Adicione condições apropriadas na cláusula WHERE para garantir isso.

2. Use Cursos para Múltiplas Linhas: Se a consulta puder retornar várias linhas, considere usar um cursor explícito ou um loop com SELECT … BULK COLLECT INTO.

Exemplo de Código com Erro

Aqui está um exemplo de código que pode gerar o erro ORA-01422:

DECLARE
    v_job_name VARCHAR2(30);
BEGIN
    SELECT job_name
    INTO v_job_name
    FROM dcl_clean_table
    WHERE table_name = 'MINHA_TABELA';
    
    DBMS_OUTPUT.PUT_LINE('Job Name: ' || v_job_name);
END;

Se a consulta SELECT job_name FROM dcl_clean_table WHERE table_name = ‘MINHA_TABELA’ retornar mais de uma linha, o erro ORA-01422 será gerado.

Soluções

1. Certifique-se de que a Consulta Retorne Apenas uma Linha

Você pode ajustar a consulta para garantir que ela retorne apenas uma linha, usando a cláusula ROWNUM ou uma função agregada, como MIN ou MAX.

DECLARE
    v_job_name VARCHAR2(30);
BEGIN
    SELECT job_name
    INTO v_job_name
    FROM (SELECT job_name FROM dcl_clean_table WHERE table_name = 'MINHA_TABELA' AND ROWNUM = 1);
    
    DBMS_OUTPUT.PUT_LINE('Job Name: ' || v_job_name);
END;

2. Use um Cursor Explícito

Se a consulta puder retornar várias linhas e você quiser processar cada linha, use um cursor explícito.

DECLARE
    CURSOR c_jobs IS
        SELECT job_name
        FROM dcl_clean_table
        WHERE table_name = 'MINHA_TABELA';
        
    v_job_name VARCHAR2(30);
BEGIN
    OPEN c_jobs;
    LOOP
        FETCH c_jobs INTO v_job_name;
        EXIT WHEN c_jobs%NOTFOUND;
        
        DBMS_OUTPUT.PUT_LINE('Job Name: ' || v_job_name);
    END LOOP;
    CLOSE c_jobs;
END;

3. Use BULK COLLECT e LOOP

Outra abordagem é usar BULK COLLECT INTO com um loop para processar várias linhas.

DECLARE
    TYPE job_name_table IS TABLE OF VARCHAR2(30);
    v_job_names job_name_table;
BEGIN
    SELECT job_name
    BULK COLLECT INTO v_job_names
    FROM dcl_clean_table
    WHERE table_name = 'MINHA_TABELA';
    
    FOR i IN 1..v_job_names.COUNT LOOP
        DBMS_OUTPUT.PUT_LINE('Job Name: ' || v_job_names(i));
    END LOOP;
END;

Conclusão

Para evitar o erro ORA-01422, certifique-se de que sua consulta SELECT … INTO retorne exatamente uma linha, ou alterne para métodos que possam lidar com múltiplas linhas, como cursores ou coleções.