Could Not Be Accessed Value Of The For Loop Counter In PL/SQL

oracleplsqlplsql-developertoad

I try to learn PL/SQL for loops in tutorials. I learn flow of control in a for loops. (And i saw that it is same with most of the other programming languages)

Here is the flow of control in a for loop:

1. The initial step is executed first, and only once. This step allows
you to declare and initialize any loop control variables.

2. Next, the condition, i.e., initial_value .. final_value is evaluated.
If it is TRUE, the body of the loop is executed. If it is FALSE, the
body of the loop does not execute and flow of control jumps to the
next statement just after the for loop.

3. After the body of the for loop executes, the value of the counter
variable is increased or decreased.

4. The condition is now evaluated again. If it is TRUE, the loop
executes and the process repeats itself (body of loop, then increment
step, and then again condition). After the condition becomes FALSE,
the FOR-LOOP terminates.

And then i want to test this steps for my worry in my TOAD IDE. I use simple sample code to test as below.

DECLARE
   a number(2) ;
BEGIN
   FOR a IN REVERSE 10 .. 20 LOOP
      dbms_output.put_line('value of a: ' || a);
   END LOOP;
END;
/

Now this loop start initial counter, initial_value and final_value. counter is 'a', initial_value is 10 and the final_value is 20. And the counter a will be the first in 20 because of the REVERSE keyword. The loop body is executed for 20. After the body is executed a is decreased. And it will be 19. And then the condition is eveluated. The condition is true because of 19 is in [10, 20]. and then for loop body is executed. This operations is contiuned at the same way. When counter a's value is 9 and then condition evaluated to FALSE.And then the loop is terminated. Flow of control jumps to the next statement just after the for loop.The counter's last value is 9. And i want to see it 9 value. so that i run below code.

DECLARE
   a number(2) ;
BEGIN
   FOR a IN REVERSE 10 .. 20 LOOP
      dbms_output.put_line('value of a: ' || a);
   END LOOP;
   dbms_output.put_line('THE FINAL VALUE OF a: ' || a);
END;
/

When the above code is executed, it produces the following result:

value of a: 20
value of a: 19
value of a: 18
value of a: 17
value of a: 16
value of a: 15
value of a: 14
value of a: 13
value of a: 12
value of a: 11
value of a: 10
THE FINAL VALUE OF a:

But i hope see the result like as below:

value of a: 20
value of a: 19
value of a: 18
value of a: 17
value of a: 16
value of a: 15
value of a: 14
value of a: 13
value of a: 12
value of a: 11
value of a: 10
THE FINAL VALUE OF a: 9

Why the counter 'a' is not connected after the loop. Why I did not see it's value to 9. Does'nt the program compiler made a real way assignment to counter 'a' ??

Best Answer

The problem is that the variable a that you declare in your declaration section is not the same as the variable a that is declared in the context of your loop. You've declared two different variables named a with different scope.

If you run your block without a declaration section, you'll notice that it works even though you aren't declaring a variable a in the declaration section. When you write a for loop, your counter is implicitly declared and is in scope only within the loop. After the end loop, you can no longer reference the variable.

BEGIN
   FOR a IN REVERSE 10 .. 20 LOOP
      dbms_output.put_line('value of a: ' || a);
   END LOOP;
END;

If you want to explicitly declare the variable you are using in your loop and you want to be able to reference the variable outside the loop, you could write a while loop

declare
  i integer;
begin
  i := 20;
  while i >= 10
  loop
    dbms_output.put_line( 'In loop: ' || i );
    i := i - 1;
  end loop;
  dbms_output.put_line( 'Final value: ' || i );
end;