You are on page 1of 19

Oracle commit Processing

A commit is a very important Oracle concept. As users make changes in Oracle, those changes
are only visible to the user session making the change and are unrecoverable in the case of a
crash. A commit changes all that. When the user tells Oracle to commit the change, Oracle makes
the change visible to everyone, and ensures that the change is recoverable.
Since RAM is wiped out if you lose power to the computer, all the redo data in the redo buffer
would be lost in a power outage. To protect against this problem, a commit asks Oracle to save
the redo to disk, which is permanent. The redo log disk files are called online redo logs.

The V$ views
Throughout the next two days lectures you will hear about the V$ views. The V$
views provide a continually updated look at internal statistics. You may hear the V$
views called dynamic performance views or tables for this reason. There are
approximately 143 or more V$ views in version 8.0.5. The views themselves are
actually constructed on top of the C structs that are at the heart of the Oracle
executable. The C structs in Oracle are named using a K$ or X$ prefix and general
cant be seen by anyone but the SYS user and then only if a view is created against
them. Figure 10 shows a sample of the layout of the V$ tables as extracted via a
partial screen shot from the RevealNet Oracle Administrator Visual Dictionary.
Figure 10: Example of the V$ view relations
How are they used?
The V$ views are used to examine current performance indicators. By using a delta
method over several equally timed selects trending can be performed. This delta
method is how many of the monitoring tools get their information about Oracle
performance. As far as I know only one tool, Precise*SQL from Precise Software
Solutions (also sold as DBTuner from EMC) samples externally directly from
memory. Quest Software is working on externally sampling but I am not aware if they
have it in production as of this writing.
The benefits of external sampling are that increased sample rates (up to 99 per second)
can be obtained with little impact on the Oracle database. Internal sampling is prone
to the same delays and problems any Oracle internal connection falls prey too, thus
limiting the sustained sample ratre that can be obtained without seriously impacting
performance.

A V$ view that is very useful for shared pool analysis is called the V$SQLAREA
view and as its name implies it is used to show the contents of the shared SQL area in
the shared pool. An example view based on the V$SQLAREA view and a companion
report are show in Source 34 and 35.
OR REPLACE VIEW sql_garbage AS
SELECT CREATE
b.username users,
SUM(a.sharable_mem+a.persistent_mem) Garbage,
TO_NUMBER(NULL) good
FROM
sys.v_$sqlarea a,
dba_users b
WHERE
(a.parsing_user_id = b.user_id AND a.executions<=1)
GROUP BY b.username
UNION
SELECT DISTINCT
b.username users,
TO_NUMBER(NULL) garbage,
SUM(c.sharable_mem+c.persistent_mem) Good
FROM
dba_users b,
sys.v_$sqlarea c
WHERE
(b.user_id=c.parsing_user_id AND c.executions>1)
GROUP BY b.username;

Listing 34: Example view using the V$SQLAREA View


COLUMN garbage FORMAT A14 HEADING 'Non-Shared SQL'
COLUMN good FORMAT A14 HEADING 'shared SQL'
COLUMN good_percent FORMAT A14 HEADING 'Percent Shared'
COLUMN users FORMAT A14 HEADING Users
COLUMN nopr NOPRINT
SET FEEDBACK OFF
@title80 'Shared Pool Utilization'
SPOOL rep_out\&db\sql_garbage
SELECT 1 nopr,
a.users users,
TO_CHAR(a.garbage,'9,999,999,999') garbage,
TO_CHAR(b.good,'9,999,999,999') good,
TO_CHAR((b.good/(b.good+a.garbage))*100,'9,999,999.999') good_percent
FROM sql_garbage a, sql_garbage b
WHERE a.users=b.users
AND a.garbage IS NOT NULL AND b.good IS NOT NULL
UNION
select 2 nopr,
'-------------' users,'--------------' garbage,'--------------' good,
'--------------' good_percent FROM dual
UNION
SELECT 3 nopr,

TO_CHAR(COUNT(a.users)) users,
TO_CHAR(SUM(a.garbage),'9,999,999,999') garbage,
TO_CHAR(SUM(b.good),'9,999,999,999') good,
TO_CHAR(((SUM(b.good)/(SUM(b.good)+SUM(a.garbage)))*100),'9,999,999.999')
good_percent
FROM sql_garbage a, sql_garbage b
WHERE a.users=b.users
AND a.garbage IS NOT NULL AND b.good IS NOT NULL
ORDER BY 1,3 DESC
/
SPOOL OFF
CLEAR COLUMNS

Source 35: Example Report using View Based on V$SQLAREA


Example results from the report shown in Source 35 are shown in Listing 34.
Date: 01/28/00
Time: 10:45 AM

Shared Pool Utilization


dw database

Page:
MAULT

Users
Non-Shared SQL Shared SQL
Percent Shared
-------------- -------------- -------------- -------------ASMITH
371,387,006
1,007,366
.271
NETSPO
10,603,456
659,999
5.860
DCHUN
6,363,158
151,141
2.320
DSSUSER
5,363,057
824,865
13.330
MRCHDXD
4,305,330
600,824
12.246
DWPROC
2,690,086
4,901,400
64.564
CWOODY
946,199
239,604
20.206
TTERIFIC
877,644
93,323
9.611
GCMATCH
604,369
1,637,788
73.045
MAULT
445,566
3,737,984
89.350
PRECISE
205,564
46,342,150
99.558
BWITE
154,754
35,858
18.812
SYS
146,811
9,420,434
98.465
SSMITH
102,460
8,523,746
98.812
MRCHPHP
56,954
59,069
50.911
MRCHAEM
42,465
65,017
60.491
------------- -------------- -------------- -------------16
404,553,888
78,358,468
16.226

Listing 34: Example Output from the SQL GARBAGE Report


Other useful V$ views are shown in Table 11.
View Name

Description

V$SQLTEXT

Contains full SQL text of stored SQL area

V$SYSSTAT

Contains overall system level statistics

V$SESSTAT

Contains session statistics

V$SESSION

Contains information on current sessions

V$ROLLSTAT

Contains statistics on rollback segments

V$ROLLNAME

Contains rollback segment names

V$SGA

Contains information on SGA areas (rollup


from V$SGASTAT)

V$SGASTAT

Contains information on SGA segment


sizes

V$INSTANCE

Contains information on the instance

V$PARAMETER

Contains settings for all initialization


parameters

V$DB_OBJECT_CACHE

Contains information on the SGA Object


Caches

V$LIBRARYCACHE

Contains information on the shared pool


library caches

V$LOG

Contains information on all current redo


logs

V$LOG_HIST(ORY)

Contains information on redo log switches

V$LOGFILE

Contains locations of all redo log files

V$FIXED_VIEW_DEFINITION

Contains the definitions for all V$ and


GV$ views

Table 11: Views Useful for Monitoring and Tuning


Table 11 only lists those views I use regularly, you will in the presentation on tuning
that several others are useful for specific monitoring of the database buffers and locks
as well.

Programming in PL/SQL
Databases have been in use long before the personal computer arrived on the scene.
IBM developed the Structured Query Language standard (dubbed SQL, and
pronounced See-Quel) over 30 years ago as a way to retrieve data from their new
relational database. A decade later, Oracle released the first commercial relational
database that used SQL, and SQL has become the de-facto query language for the vast
majority of popular database products.
For the complete story, we recommend the book Easy Oracle PL/SQL
Programming. Once you have mastered basic SQL you are ready for the advanced
book Oracle PL/SQL Tuning by Dr. Timothy Hall.
Even though SQL is the standard language for interacting with any modern database,
it does not mean that SQL is without limitations. If we want to retrieve a set of
records from the database and modify them according to a set of rules, (updating some
and returning to the calling program others), we cant do this with a single SQL call to
the database. Complex processing requires the ability to compare values (often called
Boolean logic) and implement programmatic flow control. In other words, some type
of programming language was required to process the returned rows and implement
the program rules. To achieve this capability, Oracle introduced the Procedural
Language extensions to the Structured Query Language or PL/SQL.
Oracle PL/SQL was based on the ADA programming language which was developed
by the Department of Defense to be used on mission critical systems. Although not a
sexy language like Java or C, ADA is still being develop and used for applications
such as aircraft control systems. ADA is a highly structured, strongly typed

programming language that uses natural language constructs to make it easy to


understand. The PL/SQL language inherited these attributes making PL/SQL easier to
read and maintain than more cryptic languages such as C. For example, below are
two loops, one in PL/SQL and the other in a programming language called C.
for x in v_start..v_finish --PL/SQL
loop
v_int := v_int +1;
end loop;
As opposed to:
for (x = str; x< fin; x++) {i++}

--C

As we see, the PL/SQL statement is more verbose but also easier to understand.
PL/SQL is also portable within the Oracle database family and runs on all supported
Oracle platforms including Oracle10g grid database. Even more important is platform
independence, where programs developed in PL/SQL on a Windows Oracle database
will load and run in a UNIX Oracle database. With each release of the Oracle
database, Oracle Corporation enhances the capabilities and performance of PL/SQL.
Remember, PL/SQL is an Oracle only product, and no other database management
system will run PL/SQL.
Unlike other languages that execute externally, PL/SQL executes inside the database.
This means that you can take advantage of PL/SQLs exceptional ability to manipulate
data in the database without paying the network penalty of retrieving the data out of
the database and them updating it back to the database. Because PL/SQL runs inside
the database it takes advantage of the capabilities and capacity of the database server.
Traditionally, PL/SQL has been a compiled/interpreted language similar to Java.
When PL/SQL code is loaded into the database it is compiled into an intermediate
form, similar to the way Java is compiled into byte-code. This intermediate code is
portable across Oracle databases. Later versions of Oracle (Oracle9i and 10g) will
compile PL/SQL into native code for over 60 hardware platforms. This natively
compiled code runs more efficiently, but it loses the ability to move to other Oracle
databases without recompiling.

Lastly, placing the code that interacts with the database in PL/SQL makes better use of
the database resources. PL/SQL packages are loaded as a package so as your program
calls for data, the procedures and functions are already in cached memory. Using
PL/SQL will also result in your application using bind variables. The only way not to
use bind variables in PL/SQL is to implement dynamic SQL (discussed in Chapter 5).
The Database Administrator (DBA) also benefits when developers place their SQL
inside PL/SQL because they have access to the statements for tuning. For example
the DBA can tune the SQL (adding hints, reordering the WHERE clause) without
impacting the existing application. Placing SQL inside PL/SQL also allows the code
to be protected by the recovery capabilities of the Oracle database.
PL/SQL is the most common language for Oracle the world, and developers are
realizing the benefits in both application performance and database performance by
implementing the database interaction in PL/SQL. There are even websites built
entirely using PL/SQL. For example, Oracles HTML-DB product is installed in the
database and consists primarily of PL/SQL packages and Java scripts.

PL/SQL Basic Structure


Like the ADA programming language, PL/SQL is based on blocks, and PL/SQL
provides a number of different blocks for different uses. The characteristics of a block
include:
* A block begins with a declarative section where variables are defined.
* This is followed by a section containing the procedural statements surrounded by the
BEGIN and END key words. Each block must have a BEGIN and END statement,
and may optionally include an exception section to handle errors. The exception
section is covered later in the book.
Here is an example of a simple block:
SQL>
2
3
4
5
6
7

declare
v_line varchar2(40);
begin
v_line := 'Hello World';
dbms_output.put_line (v_line);
end;
/

Hello World

In the example above, the variable v_line is defined in the declarative section on line
2. Like SQL statements, each line ends with a semicolon. Once v_line is defined, it

can be used in the procedural section. First, v_line is assigned the literal string Hello
World on line 4. Strings are surrounded by single quotes in SQL and PL/SQL. The
v_line variable is then placed in the output buffer using the procedure
dbms_output.put_line.
In PL/SQL, the semicolon defines the end of a line of code. To execute the PL/SQL
block, use the forward slash / on a line by itself as shown on line 7. If you forget
the forward slash, SQL*Plus will simply wait for the next line to be entered.
Note: If you execute a PL/SQL script and SQL*Plus returns a number, it probably is
an indication that you forgot to place the/ at the end of your script. SQL*Plus is
actually waiting for the next line. Entering a / will execute the script.
A PL/SQL block with no name is called an anonymous block. It starts with the
declare key word to define the declarative section.
declare
define variables here
begin
code goes here
exceptions
end;

A named block is a procedure or a function. The name portion defines the declarative
section so the DECLARE key word is not used.
create procedure my_proc
as
define variables here
begin
code goes here
exceptions
end;

A procedure can be passed and change variables. A function can be passed variables
and must return a variable.
create function my_func (v_name varchar2)return number
as
define variables here
begin
code goes here
return n_jobNum;
end;

When variables are passed to a procedure or function they can be IN, OUT or
INOUT. An IN variable is passed into the procedure or function and is used, but can
not be changed. An OUT variable is passed to the procedure but it can be changed
and left in the changed state when the procedure ends.

An INOUT variable is passed to a procedure or function, and it can be used by the


block, changed by the block, and left in a changed state when the block ends. A
function can only be passed an IN variable and must return a variable. If this is
confusing, dont worry. When we get to name blocks and provide some examples it
will be much clearer.
Displaying PL/SQL Output
Another change with PL/SQL from SQL is that the database does not return the output. PL/SQL
code normally will change data, insert values, and so forth, inside the database. It will not
normally display results back to the user. To do this we use a procedure called
dbms_output.put_line to place the results in a buffer that SQL*Plus will retrieve and display.
SQL*Plus must be told to retrieve data from this buffer in order to display the results. The
SQL*Plus command set serveroutput on causes SQL*Plus to retrieve and display the buffer.
SQL>
2
3
4
5
6
7

declare
v_line varchar2(40);
begin
v_line := 'Hello World';
dbms_output.put_line (v_line);
end;
/

PL/SQL procedure successfully completed.


SQL> set serveroutput on
SQL> declare
2
v_line varchar2(40);
3 begin
4
v_line := 'Hello World';
5
dbms_output.put_line (v_line);
6 end;
7 /
Hello World
PL/SQL procedure successfully completed.

The first time the script is run, the result was just a notice that the script completed successfully.
Once we set serverouput on and rerun the script, the results are shown.
As discussed earlier, this is an anonymous block of PL/SQL code. It is sent to the database,
compiled and executed, then SQL*Plus retrieves the results. The script is stored in the
SQL*Plus buffer and can be rerun by executing the forward slash.
SQL> /
Hello World
PL/SQL procedure successfully completed.

The script is not stored in the database (like a stored or named procedure). It must be resent to
the database and compiled each time it is executed.

For the complete story, we recommend the book Easy Oracle PL/SQL Programming. Once
you have mastered basic SQL you are ready for the advanced book Oracle PL/SQL Tuning by
Dr. Timothy Hall.
As with SQL statements, SQL*Plus variables can be used to make the PL/SQL script dynamic.
Just as with a SQL statement, the variables are local to SQL*Plus and are substituted before the
code is sent to the database.
SQL> declare
2
v_line varchar2(40);
3 begin
4
v_line := 'Hello &name';
5
dbms_output.put_line (v_line);
6 end;
7 /
Enter value for name: John
old
4:
v_line := 'Hello &name';
new
4:
v_line := 'Hello John';
Hello John

The SQL*Plus accept command is a more flexible method of embedding dynamic data in the
script.
SQL> accept v_string prompt "Enter Your First Name: "
Enter Your First Name: Thomas
SQL>
2
3
4
5
6
7
old
new

declare
v_line varchar2(40):= '&v_string';
begin
v_line := 'Hello '||v_line;
dbms_output.put_line (v_line);
end;
/
2:
2:

v_line varchar2(40):= '&v_string';


v_line varchar2(40):= 'Thomas';

Hello Thomas
PL/SQL procedure successfully completed.

Lets look at this script a little closer. The first line is the SQL*Plus accept command to get the
SQL*Plus variable v_string. This line must be executed alone, not part of the PL/SQL block. At
the prompt the name Thomas was entered. Now the script is run but it is slightly modified from
previous examples.
SQL> declare
2
v_line varchar2(40):= '&v_string';

The variable v_line is declared as a varchar2(40) and is given a default value that equals
v_string. The PL/SQL assignment operator (:=) is used to assign the value. Hence, v_line is a
bucket that gets assigned the string Thomas. A developer would read an assignment statement
in English as v_line gets v_string to indicate the assignment. Lets examine a more complex
assignment statement.
4

v_line := 'Hello '||v_line;

Line 4 uses the concatenate operator to append Hello to the front of v_line and then assigns it
back to the variable v_line. The variable v_line now contains the string Hello Thomas. Line 5
places the value of v_line in the buffer to be retrieved by SQL*Plus.
old
new

2:
2:

v_line varchar2(40):= '&v_string';


v_line varchar2(40):= 'Thomas';

These two lines demonstrate SQL*Pluss verify function showing us what is substituted before
the code is sent to the database for execution. This information can be switched on/off with the
verify command
SQL> set verify on
SQL> set verify off

PL/SQL Variable Declaration and Conversion


In the previous examples a variable v_line was defined. All variables are defined in the
declaration section of the block. Variables are defined in the form:
variableName

datatype

:= defaultvalue;

Below are examples of variables. Variables can be defined as any valid datatype to include user
defined datatypes and records.
declare
v_str1
v_str2
d_today
n_sales
n_order
begin

varchar2(80);
varchar2(30) := Hello World;
date;
number;
number(8);

A constant is defined the same way a variable is with the key word constant.
c_standard constant number := 90;
Notice that a constant must be assigned a value and the above statement does four things:
* Names the variable c_standard

* Defines c_standard as a constant


* Defines c_standard as a numeric datatype
* Assigns a value of 90 to c_standard
With PL/SQL constants, note that a constant value cant be changed unless it is redefined in a
subsequent block.
In the examples above our two variables are defined as numbers, and we are now ready to see
how to include the precision and scale for a number. As in SQL, PL/SQL supports mathematical
operations and has a large library of mathematical functions, covering everything from advanced
multivariate statistics to Newtonian Calculus. PL/SQL also supports single-row functions to
convert numbers to characters and characters to numbers.

PL/SQL IF/THEN/ELSE Statements


The IF/THEN statement checks a Boolean value or expression and if true, executes
the statements in the THEN clause. If the condition is false, the statements in the
THEN clause are skipped and execution jumps to the END IF, and the expression that
is checked must return a true or false. It can be a simple Boolean variable or a
compound expression joined with AND/OR clauses, and the expression can even be a
PL/SQL function that returns a Boolean value.
There is no requirement to surround the expression with parenthesis but most
developers use parentheses for clarity. The THEN clause can contain a single or
multiple statements, or a nested PL/SQL block. Here is an example of a basic
IF/THEN statement with a THEN clause.
if v_numb > 5 then
v_numb

:= 5;

v_other := 10;
end if;

In the statements above, the Boolean condition (v_numb > 5) must be true before the
THEN clause is executed. If v_numb is equal to or less than 5, or if it evaluates to
NULL, the program control jumps to the statement after the END IF clause. Note that

the THEN clause can contain any number of valid PL/SQL statements. The variable
v_other and v_numb will not change unless the condition is true.
Note: All the IF/THEN statements must end with an END IF clause. The PL/SQL
engine will continue to include statements in the THEN clause until it encounters an
END IF. If you get a compile error that states: found xxxx when expecting IF, the
compiler encountered an END statement before it encountered the END IF. Simply
find the end of you IF statement and close it with an END IF to correct the problem.
Sometimes the program flow will want to branch one direction if the condition is true
and another direction if the condition is false, and this is handled within the
IF/THEN/ELSE statement.
Like the IF/THEN statement, the THEN clause statements will only be executed if the
condition is true. However if the condition is false, the statements in the ELSE clause
are executed. This is an either-or situation.
if n_numb > 5 then
v_status := large;
else
v _status := small;
end if;
For the complete story, we recommend the book Easy Oracle PL/SQL
Programming. Once you have mastered basic SQL you are ready for the advanced
book Oracle PL/SQL Tuning by Dr. Timothy Hall.
After executing the example, the variable v_status will be defined as either large or
small. Note that the above statement could also be written as two separate IF
statements.
if n_numb > 5 then v_status := large; end if;
if n_numb <=5 then v_status := small; end if;

Programmatically, the results are the same, however the two IF statements required
two evaluations, while the IF/THEN/ELSE statement requires only one evaluation.

The PL/SQL WHILE Loop


The WHILE loop, also called a conditional loop, evaluates a condition before each
loop executes, and if false, the loop is terminated. If the expression is false when the
program reaches the WHILE loop, the loop code is jumped and never executed. Use a
WHILE loop when the condition test is required at the start of the loop. The next
example contains three WHILE loops.
SQL> declare
2
v_test varchar2(8) := 'RUN';
3
n_numb number := 2;
4 begin
5
while v_test <> 'STOP' loop
6
if n_numb > 5
7
then v_test := 'STOP';
8
end if;
9
dbms_output.put_line (v_test||': '||n_numb);
10
n_numb := n_numb + 1;
11
end loop;
12
13
v_test := 'DOWN';
14
while n_numb > 1 AND v_test = 'DOWN' loop
15
dbms_output.put_line (v_test||': '||n_numb);
16
n_numb := n_numb - 1;
17
end loop;
18
19
while 7 = 4 loop
20
NULL; -- never get here
21
end loop;
22 end;
23 /
RUN: 2
RUN: 3
RUN: 4
RUN: 5
STOP: 6
DOWN: 7
DOWN: 6
DOWN: 5
DOWN: 4
DOWN: 3
DOWN: 2

The last loop will never execute because the condition will never be true. The middle
loop uses multiple condition tests, using the AND key word. The first loop runs while
v_test does not equal STOP. Notice that the check that changes v_test in lines 6, 7,
8 is at the top of the loop. This is a poor choice because even though v_test may
change, it is not evaluated again until the program gets back to the top of the loop.
This results in the output stopping after n_numb reached 6, but notice in the results
that at completion of the first loop, n_numb was left with a value of 7. Unless this
was the programmers intent, a small, hard to locate bug has been introduced into the
code.
For the complete story, we recommend the book Easy Oracle PL/SQL
Programming. Once you have mastered basic SQL you are ready for the advanced
book Oracle PL/SQL Tuning by Dr. Timothy Hall.

The programmer must ensure that the order of the statements inside the loop will
leave the variables in the required state when the loop terminates. Remember that the
WHILE loop tests at the start of the loop and does not test again until the loop has
completely run and returned to the loop start. Both the endless loop and the WHILE
loop execute until a condition is met. These loops are effective if the programmer
does not know how many times the loop will execute. If the loop will run for a
specified number of iterations, it is more efficient to use a FOR loop.
The PL/SQL REPEAT-UNTIL Loop
The WHILE loop test at the start of the loop and it the condition is false, the loop code
is never executed. If you want to ensure that the loop code is executed at least one,
the test must be preformed at the bottom of the loop. This is referred to as a REPEATUNTIL or DO-WHILE loop. PL/SQL does not directly implement a REPEAT-UNTIL
loop however it is easy to construct one using an endless loop. By placing the EXIT
WHEN (condition = true) statement as the last line of code in an endless loop you will
achieve the same results.
SQL> declare
2
n_num number := 1;
3 begin
4
loop
5
dbms_output.put(n_num||', ');
6
n_num := n_num + 1;
7
exit when n_num > 5;
8
end loop;
9
dbms_output.put_line('Final: '||n_num);
10 end;
11 /
1, 2, 3, 4, 5, Final: 6
PL/SQL procedure successfully completed.

Since the condition test is at the bottom of the loop, you ensure that the loop code is
executed at least once.
The PL/SQL FOR Loop
The FOR loop executes for a specified number of times, defined in the loop
definition. Because the number of loops is specified, the overhead of checking a
condition to exit is eliminated. The number of executions is defined in the loop
definition as a range from a start value to an end value (inclusive). The integer index
in the FOR loop starts at the start value and increments by one (1) for each loop until
it reaches the end value.
SQL> begin
2
for idx in 2..5 loop
3
dbms_output.put_line (idx);

2
3
4
5

4
5
6

end loop;
end;
/

PL/SQL procedure successfully completed.

In the example below a variable idx is defined, assigning it the value 100. When the
FOR loop executes, the variable idx is also defined as the index for the FOR loop.
The original variable idx goes out of scope when the FOR loop defines its index
variable. Inside the FOR loop, the idx variable is the loop index. Once the FOR loop
terminates, the loop index goes out of scope and the original idx variable is again in
scope.
SQL>
2
3
4
5
6
7
8
9
10
100
2
3
4
5
100

declare
idx number := 100;
begin
dbms_output.put_line (idx);
for idx in 2..5 loop
dbms_output.put_line (idx);
end loop;
dbms_output.put_line (idx);
end;
/

PL/SQL procedure successfully completed.

You can use the loop index inside the loop, but you can not change it. If you want to
loop by an increment other than one, you will have to do so programmatically as the
FOR loop will only increment the index by one.
SQL> begin
2
for i in 4 .. 200 loop
3
i := i + 4;
4
end loop;
5 end;
6 /
i := i + 4;
*
ERROR at line 3:
ORA-06550: line 3, column 5:
PLS-00363: expression 'I' cannot be used as an assignment target

ORA-06550: line 3, column 5:


PL/SQL: Statement ignored

The loop index start and stop values can be expressions or variables. They are
evaluated once at the start of the loop to determine the number of loop iterations. If
their values change during the loop processing, it does not impact the number of
iterations.
SQL>
2
3
4
5
6
7
8
9
10
3
4
5
6

declare
n_start number := 3;
n_stop number := 6;
begin
for xyz in n_start .. n_stop loop
n_stop := 100;
dbms_output.put_line (xyz);
end loop;
end;
/

PL/SQL procedure successfully completed.

Line 6 changes the stop value, setting it to 100. But the loop still terminates at the
value of 6. The loop index start and stop values are always defined from lowest to
highest. If you want the index to count down use the REVERSE key word.
SQL> begin
2
for num in 4 .. 7 loop
3
dbms_output.put_line (num);
4
end loop;
5
6
for num in reverse 4 .. 7 loop
7
dbms_output.put_line (num);
8
end loop;
9
10
for num in 7 .. 4 loop
11
dbms_output.put_line (num);
12
end loop;
13 end;
14 /
4
5
6
7
7
6
5
4
PL/SQL procedure successfully completed.

Notice that the third FOR loop COMPILED BUT DID NOT EXECUTE! The FOR
loop calculated the number of loop iterations and got a negative number, therefore the
loop count was zero.
In the next example a FOR loop is used to calculate the factorial of a number. A
factorial value is commonly used to determine all possible values for a number and is
defined as x*(x-1)*(x-2).(0) = !x.
!8 = 8*7*6*5*4*3*2*1 = 40320
SQL>
2
3
4
5
6
7
8
9
10

declare
v_seed number := &numb;
v_hold number := 1;
begin
for i in reverse 1 .. v_seed loop
v_hold := v_hold * i;
end loop;
dbms_output.put_line ('!'||v_seed||' = '||v_hold);
end;
/

Enter value for numb: 8


!8 = 40320
SQL> /
Enter value for numb: 4
!4 = 24

Related PL/SQL FOR Loop Articles:


PL/SQL Cursor For Loop

PATCHING AND UPGRADATION


Question: I just applied an Oracle patch upgrade from 10.2.0.4 to 10.2.0.5.
Thev$version still shows my release as Oracle 10.2.0.3 Why isn't v$version updated
when I run a patchset?
Answer: You may be confusing patches with releases.
The v$version view only displays the last full release installed, and it does not show
patchsets and cumulative patch upgrades (CPUs).

An upgrade to a new release will change the release in v$version, but applying just a
heap of patches (a patchset) will not update the v$version view.
Try entering sqlplus and see what release level is displayed. Try this query to see if
your release has been updated:
select
comp_id,
comp_name,
version,
status
from
dba_registry;

To see applied patches, use the Oracle opatch utility:


oracle> .ORACLE_HOME\OPatch\opatch lsinventory

See here for complete details on using the opatch utility in the book Advanced
Oracle Utilities.
Also check the ad_bugs view to see all patches that are applied with the opatch utility:
select *
from
ad_bugs
where
bug_number = 'patch_number';