7

Found strange thing. Can't understand why Oracle allow this query and why cnt variable doesn't change after it's execution:

declare cnt number;
begin
 for r in (Select count(1) into cnt from  v$session) loop
   dbms_output.put_line(cnt);
 END LOOP; 
end;

Select count(1) from v$session returns not null value

Of course I've understand:

  1. That FOR doesn't need in this situation. Count without INTO retuns only one row.
  2. That I can use it without INTO and it will works.

Just curious how and why it works in query above.

It's strange why Oracle allow subquery with SELECT INTO, because in common situation Oracle returns compilation error ORA-06550

declare cnt number;
 begin
        select count(1) from  (Select count(1) into cnt from  v$session)
 end;
or 

And if first query works - why it doesn't return cnt value correctly?

1
  • 1
    please have a look at my answer. You should name your columns in the for select statement. Handle r like a table row. Commented Oct 15, 2015 at 8:49

2 Answers 2

4

Correct sql statement

try this

declare cnt number;
begin
 for r in (Select count(1) as cnt from  v$session) loop
   dbms_output.put_line(r.cnt);
 END LOOP; 
end;

Explanation

select_statement

SQL SELECT statement (not PL/SQL SELECT INTO statement). For select_statement, PL/SQL declares, opens, fetches from, and closes an implicit cursor. However, because select_statement is not an independent statement, the implicit cursor is internal—you cannot reference it with the name SQL.

see http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/cursor_for_loop_statement.htm#LNPLS1155

the cnt variable is ignored, this can be proved by the following example, because no error is raised:

declare
  cnt       number;
  a_varchar varchar2(1);
begin
  for r in (Select 'AA' into a_varchar from v$session) loop
    dbms_output.put_line(a_varchar);
  end loop;
end;
Sign up to request clarification or add additional context in comments.

8 Comments

@RaduGheorghiu I've tested it without problems.
My bad, I've made a mistake in my code. You're correct.
Yep, it works. +1 to answer. But this doesn't explain why it works incorrect with INTO
@ViktorBardakov That's right, this is unclear. I've upvoted your question for more attention
@sstan you are right, i have merged the second answer to the first.
|
2

Very interesting, I'd say this is a bug except it's a benign one. The INTO cnt bit is valid PL/SQL but is ignored in this context, which can be proven with a simple test case:

declare cnt number;
begin
 for r in (select count(1) into cnt from dual) loop
   dbms_output.put_line('cnt=' || cnt);
   dbms_output.put_line('r=' || r."COUNT(1)");
 end loop;
end;

As you can see, the INTO clause is ignored, and as expected the r record is correctly populated. Output on my 11gR2 instance:

cnt=
r=1

1 Comment

A slightly more interesting test case is to replace the first line with declare cnt number := -3.141; and then the output is cnt=-3.141. The INTO clause is ignored and the default value for cnt will be displayed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.