Skip to Main Content
  • Questions
  • Implicit cursor (SELECT INTO...) behavior

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Alex.

Asked: June 08, 2004 - 10:14 am UTC

Last updated: September 02, 2016 - 3:55 pm UTC

Version: 8.1.7 and 9.2

Viewed 1000+ times

You Asked

When using SELECT INTO... and have multiple rows returning by query,
if the target variable declared strongly (e.g....%TYPE), it keeps the result of a fetch,
if declared weakly (e.g....NUMBER), it keeps nothing for the same case.

What is going?

Thanks in advance.

Here is the case:

create table emp1 as select * from emp where ename = 'ALLEN'
/

insert into emp1 select * from emp1
/
commit
/

orclbal803/DTOTT/ULOG>DECLARE
2 v_empno emp1.empno%TYPE;
3 --v_empno NUMBER;
4 v_multirow_flag CHAR(1);
5 BEGIN
6 v_multirow_flag := NULL;
7 BEGIN
8 SELECT empno
9 INTO v_empno
10 FROM emp1
11 WHERE ename = 'ALLEN';
12
13 EXCEPTION
14 WHEN TOO_MANY_ROWS THEN
15 v_multirow_flag := 'Y';
16 END;
17 dbms_output.put_line('empno : '||v_empno);
18 dbms_output.put_line('multirow_flag : '||v_multirow_flag);
19
20 END;
21 /
empno : 7499
multirow_flag : Y


orclbal803/DTOTT/ULOG>DECLARE
2 --v_empno emp1.empno%TYPE;
3 v_empno NUMBER;
4 v_multirow_flag CHAR(1);
5 BEGIN
6 v_multirow_flag := NULL;
7 BEGIN
8 SELECT empno
9 INTO v_empno
10 FROM emp1
11 WHERE ename = 'ALLEN';
12
13 EXCEPTION
14 WHEN TOO_MANY_ROWS THEN
15 v_multirow_flag := 'Y';
16 END;
17 dbms_output.put_line('empno : '||v_empno);
18 dbms_output.put_line('multirow_flag : '||v_multirow_flag);
19
20 END;
21 /
empno :
multirow_flag : Y


and Tom said...

see support <Note:258112.1>


the if you

v_empno number(4);

the same thing would happen in the second block. if the variable being selected into matches 100% the table definition, plsql is setting up a bind buffer directly to the plsql variable. Otherwise it is allocating a bind area, fetching into that, and then moving upon success into the plsql variable (hence the different behaviours)




Rating

  (2 ratings)

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

Comments

Can't Find Document

D. Becker, June 08, 2004 - 12:57 pm UTC

Tried finding the document (Note:258112.1) on MetaLink in various ways. I couldn't retrieve it. Would you give us the gist of the document?

Tom Kyte
June 08, 2004 - 1:30 pm UTC

A "SELECT <column> INTO <variable> ..." causing exception TOO_MANY_ROWS (ORA-1422) will initialize the variable if it is exactly the same datatype/precision as the column selected.

in 7.3.4 , the behaviour was different. First its checked whether Select statament is going to return one OR many rows and accordingly the variable is initialised whereas in Oracle 8 and onwards, pl/sql does the initial fetch, populates the variable and then check whether more rows are to be fetched.

WORKAROUND to get the same functionality as that of 7.3.4:-
-----------------------------------------------------------

Declare the variable and column with different datatypes as shown below


declare
dummy number(5); -- different type than emp.empno ..number(4)
begin
dbms_output.put_line('Body: dummy='||dummy);
select empno into dummy from emp;

exception when too_many_rows then
dbms_output.put_line('Exception: dummy='||dummy);
dbms_output.put_line(sqlerrm);
end;
/




Tariq, September 02, 2016 - 4:39 am UTC

Declare
w_ename varchar2(10);
Begin
Begin
select ename
into w_ename
from emp
where deptno = 20;
Exception when too_many_rows then
null;
when no_data_found then
null;
end;
dbms_output.put_line('w_ename --> '||w_ename);
end;


see the output in 2 different DB version

11.2.0.4 :
w_ename --> SMITH

PL/SQL procedure successfully completed.

12.1.0.2 :
w_ename -->

PL/SQL procedure successfully completed.


may I know the reason
Connor McDonald
September 02, 2016 - 3:55 pm UTC

Well, in 12.1.0.2 either:

- The enames are null
- There aren't any rows for deptno 20
- There is more than one row for deptno 20

What do you see if you run:

select * from emp where deptno = 20;

in your 12 database?

More to Explore

DBMS_OUTPUT

More on PL/SQL routine DBMS_OUTPUT here