Skip to Main Content

SQL & PL/SQL

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Populating OUT parameters when TOO_MANY_ROWS exception is thrown

JustinCaveJul 4 2011 — edited Jul 5 2011
When I was trying to write code to test out today's PL/SQL challenge quiz, the behavior appears to depend on the table being queried. I can't figure out what attribute of the table drives the behavior (or if there is a different explanation for the behavior).

The quiz is testing what happens when a procedure does a SELECT INTO an OUT parameter and a TOO_MANY_ROWS exception is thrown. The intent is to show that even though the behavior is technically undefined, what actually happens is that the OUT parameter is populated with the first row that is selected (obviously, you would never write code that depends on this behavior-- this is solely an academic exercise). The demonstration code works as expected
CREATE TABLE plch_emp ( emp_name VARCHAR2(100) );

INSERT INTO plch_emp VALUES ('Jones');

INSERT INTO plch_emp VALUES ('Smith');

COMMIT;

CREATE OR REPLACE PROCEDURE plch_get
  (out_name OUT plch_emp.emp_name%TYPE) IS
BEGIN
  SELECT emp_name
  INTO out_name
  FROM plch_emp
  ORDER BY emp_name;
EXCEPTION
  WHEN OTHERS THEN
    dbms_output.put_line('A:' || out_name);
END;
/
What will be displayed after executing the following block:

DECLARE
  l_name plch_emp.emp_name%TYPE;
BEGIN
  plch_get(l_name);
  dbms_output.put_line('B:' || l_name);
END;
/
and outputs
A:Jones
B:Jones
When I replicate the logic while hitting the EMP table, the PLCH_EMP table, and the newly created EMP2 table, however, I get different behavior for the EMP and EMP2 tables. The procedure that queries PLCH_EMP works as expected but the OUT parameter is NULL when either EMP or EMP2 are created. Any idea what causes the behavior to differ?
select *
  from v$version;

create table emp2
as
select *
  from emp;

create or replace procedure p1( p_out out varchar2 )
is
begin
  select emp_name
    into p_out
    from plch_emp
   order by emp_name;
exception
  when others then 
    dbms_output.put_line( 'P1 A:' || p_out );
end;
/

create or replace procedure p2( p_out out varchar2 )
is
begin
  select ename
    into p_out
    from emp
   order by ename;
exception
  when others then 
    dbms_output.put_line( 'P2 A:' || p_out );
end;
/

create or replace procedure p3( p_out out varchar2 )
is
begin
  select ename
    into p_out
    from emp2
   order by ename;
exception
  when others then 
    dbms_output.put_line( 'P3 A:' || p_out );
end;
/

declare
  l_ename varchar2(100);
begin
  p1( l_ename );
  dbms_output.put_line( 'P1 B:' || l_ename );

  p2( l_ename );
  dbms_output.put_line( 'P2 B:' || l_ename );

  p3( l_ename );
  dbms_output.put_line( 'P3 B:' || l_ename );

end;
/

SQL> select *
  2    from v$version;

BANNER
--------------------------------------------------------------------------------

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0      Production
TNS for 64-bit Windows: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

SQL>
SQL> create table emp2
  2  as
  3  select *
  4    from emp;

Table created.

SQL>
SQL> create or replace procedure p1( p_out out varchar2 )
  2  is
  3  begin
  4    select emp_name
  5      into p_out
  6      from plch_emp
  7     order by emp_name;
  8  exception
  9    when others then
 10      dbms_output.put_line( 'P1 A:' || p_out );
 11  end;
 12  /

Procedure created.

SQL>
SQL> create or replace procedure p2( p_out out varchar2 )
  2  is
  3  begin
  4    select ename
  5      into p_out
  6      from emp
  7     order by ename;
  8  exception
  9    when others then
 10      dbms_output.put_line( 'P2 A:' || p_out );
 11  end;
 12  /

Procedure created.

SQL>
SQL> create or replace procedure p3( p_out out varchar2 )
  2  is
  3  begin
  4    select ename
  5      into p_out
  6      from emp2
  7     order by ename;
  8  exception
  9    when others then
 10      dbms_output.put_line( 'P3 A:' || p_out );
 11  end;
 12  /

Procedure created.

SQL>
SQL> declare
  2    l_ename varchar2(100);
  3  begin
  4    p1( l_ename );
  5    dbms_output.put_line( 'P1 B:' || l_ename );
  6
  7    p2( l_ename );
  8    dbms_output.put_line( 'P2 B:' || l_ename );
  9
 10    p3( l_ename );
 11    dbms_output.put_line( 'P3 B:' || l_ename );
 12
 13  end;
 14  /
P1 A:Jones
P1 B:Jones
P2 A:
P2 B:
P3 A:
P3 B:

PL/SQL procedure successfully completed.
Justin
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Aug 2 2011
Added on Jul 4 2011
14 comments
1,124 views