Skip to Main Content

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Subhash.

Asked: October 18, 2017 - 5:25 pm UTC

Last updated: October 20, 2017 - 1:26 am UTC

Version: 12.1

Viewed 1000+ times

You Asked

Hi,
I am facing "ORA-01422: exact fetch returns more than requested number of rows" in my plsql procedure.
Here are the details of test I am trying:

create table cust_bug_metadata(product_id number, component varchar2(50),sub_component varchar2(50), email varchar2(50))
insert into cust_bug_metadata(product_id, component, sub_component, email) values(5757, 'extract', 'checkpoint','subhas@oracle.com')
insert into cust_bug_metadata(product_id, email) values(5757,'subhas@oracle.com')

Now create a procedure:

create or replace procedure "SEND_BUG_EMAIL_DAILY"
is
component_value VARCHAR2(200);
sub_component_value VARCHAR2(200);
cursor mailCursor is select product_id from cust_bug_metadata;
begin
FOR m IN mailCursor LOOP
select component,sub_component into component_value,sub_component_value from cust_bug_metadata where product_id = m.product_id;
END LOOP;
end;

Procedure gets created.

now when running this procedure:

begin
SEND_BUG_EMAIL_DAILY;
end
/

I am getting "ORA-01422: exact fetch returns more than requested number of rows"

This is because I am using product_id as 5757 in both the rows but this has to be in my table as per requirement.
Could you please let me know on how to avoid this error with having same product_id in both the row.

Thanks,
Subhash

and Connor said...

That depends on what you are trying to achieve.

SQL> create table cust_bug_metadata(product_id number, component varchar2(50),sub_component varchar2(50), email varchar2(50));

Table created.

SQL> insert into cust_bug_metadata(product_id, component, sub_component, email) values(5757, 'extract', 'checkpoint','subhas@oracle.com');

1 row created.

SQL> insert into cust_bug_metadata(product_id, email) values(5757,'subhas@oracle.com');

1 row created.

SQL>
SQL>
SQL> create or replace procedure "SEND_BUG_EMAIL_DAILY"
  2  is
  3  component_value VARCHAR2(200);
  4  sub_component_value VARCHAR2(200);
  5  cursor mailCursor is select product_id from cust_bug_metadata;
  6  begin
  7  FOR m IN mailCursor LOOP
  8    select component,sub_component into component_value,sub_component_value from cust_bug_metadata where product_id = m.product_id;
  9  END LOOP;
 10  end;
 11  /

Procedure created.

SQL>
SQL>
SQL> exec SEND_BUG_EMAIL_DAILY;
BEGIN SEND_BUG_EMAIL_DAILY; END;

*
ERROR at line 1:
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "MCDONAC.SEND_BUG_EMAIL_DAILY", line 8
ORA-06512: at "MCDONAC.SEND_BUG_EMAIL_DAILY", line 8
ORA-06512: at line 1

--
-- if you want to cycle through all rows, then just add another cursor
--

SQL>
SQL> create or replace procedure "SEND_BUG_EMAIL_DAILY"
  2  is
  3  component_value VARCHAR2(200);
  4  sub_component_value VARCHAR2(200);
  5  cursor mailCursor is select product_id from cust_bug_metadata;
  6  begin
  7  FOR m IN mailCursor LOOP
  8    for inner in ( select component,sub_component into component_value,sub_component_value from cust_bug_metadata where product_id = m.product_id )
  9    loop
 10      do_something;
 11    end loop;
 12  END LOOP;
 13  end;
 14  /

Procedure created.

--
-- if you want to pick just one (arbitrary) row, you can add a predicate with rownum
--

SQL>
SQL> exec SEND_BUG_EMAIL_DAILY;

PL/SQL procedure successfully completed.

SQL>
SQL> create or replace procedure "SEND_BUG_EMAIL_DAILY"
  2  is
  3  component_value VARCHAR2(200);
  4  sub_component_value VARCHAR2(200);
  5  cursor mailCursor is select product_id from cust_bug_metadata;
  6  begin
  7  FOR m IN mailCursor LOOP
  8    select component,sub_component into component_value,sub_component_value from cust_bug_metadata where product_id = m.product_id and rownum = 1;
  9  END LOOP;
 10  end;
 11  /

Procedure created.

SQL>
SQL> exec SEND_BUG_EMAIL_DAILY;

PL/SQL procedure successfully completed.

--
-- if you know a particular criteria that will always give just one matching row (eg component = null in my test case), then use that
--

SQL>
SQL> create or replace procedure "SEND_BUG_EMAIL_DAILY"
  2  is
  3  component_value VARCHAR2(200);
  4  sub_component_value VARCHAR2(200);
  5  cursor mailCursor is select product_id from cust_bug_metadata;
  6  begin
  7  FOR m IN mailCursor LOOP
  8    select component,sub_component into component_value,sub_component_value from cust_bug_metadata where product_id = m.product_id and component is not null;
  9  END LOOP;
 10  end;
 11  /

Procedure created.

SQL>
SQL> exec SEND_BUG_EMAIL_DAILY;

PL/SQL procedure successfully completed.

SQL>
SQL>


Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Pls have a look again

Subhash Kumar, October 19, 2017 - 6:08 am UTC

Thanks Connor for your response.
I used your first suggestion.

I have following procedure:

create or replace procedure "SEND_BUG_EMAIL_DAILY"
is
component_value VARCHAR2(200);
sub_component_value VARCHAR2(200);
cursor mailCursor is select product_id from cust_bug_metadata;
begin
FOR m IN mailCursor LOOP
for inner in ( select component,sub_component into component_value,sub_component_value from cust_bug_metadata where product_id = m.product_id )
loop
dbms_output.put_line(component_value);
dbms_output.put_line(sub_component_value);
end loop;
END LOOP;
end;
/

when executing this procedure I am not seeing any value coming out of dbms_output.put_line and looks like component_value and sub_component_value are not getting any value
Connor McDonald
October 20, 2017 - 1:26 am UTC

I used your first suggestion.

No you didn't :-)

Compare yours with mine and you'll see the differences (hint: "into")

More to Explore

Administration

Need more information on Administration? Check out the Administrators guide for the Oracle Database