3 - plsql for beginners
TRANSCRIPT
-
8/14/2019 3 - PLSQL for Beginners
1/30
An
Training Guide
PL/SQLfor
BeginnersSupplement
-
8/14/2019 3 - PLSQL for Beginners
2/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 2
Supplement
The supplement covers a couple of topics that are
what you might call Advanced PL/SQL, the word
Advanced is purely relative, so a more appropriate
title may have been, "Some PL/SQL we didnt have
time for".
The PL/SQL for Beginners guide introduced you to
PL/SQL, the topics covered were based on what you
are most likely to come across in your early
developments.
I have picked the topics in this document based on
the fact that you are likely to use them from a
potential pot of hundreds of topics.
The style in which the topics are presented isdifferent to that of the training course. The main
course is in a tutorial style, whereas these topics are
much lighter in detail and by example.
-
8/14/2019 3 - PLSQL for Beginners
3/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 3
Topics Covered
The following topics are covered:-
PL/SQL Records & Tables
Host File Access with UTL_FILE
-
8/14/2019 3 - PLSQL for Beginners
4/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 4
PL/ SQL Records & Tables
-
8/14/2019 3 - PLSQL for Beginners
5/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 5
PL/ SQL Records & Tables
Records
We have already seen PL/SQL records, remember
the variables you created which used the %ROWTYPE
keyword in their declaration; this is a record, for
example,
r_employee emp_cur%ROWTYPE;
The above record r_employee is a composite
datatype containing all the columns found in the
cursor emp_cur. A record could also be created
containing all the columns on a table:-
r_employee emp%ROWTYPE;
Each element of a record is referenced using dot
notation, for example, to reference the ename
element of the r_employee record you would use:-
r_employee.ename.
You are not restricted to creating records that are
anchored to a cursor or table, you can define your
own records with the TYPE statement.
-
8/14/2019 3 - PLSQL for Beginners
6/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 6
PL/ SQL Records & Tables
Records
To create a record manually that contains employee
information you might use the following:-
TYPE t_emp_record IS RECORD
( enumber NUMBER
, firstname VARCHAR2(20)
, lastname VARCHAR2(20));
At this point, no PL/SQL object exists, just the new
datatype, so, we need to declare a variable of this
type:-
l_employee t_emp_record;
This is no different to declaring a variable of any of
the standard types. You can now use the new
l_employee record with the dot notation to get at
its elements, for example:-
l_employee.enumber := 100;
l_employee.firstname := 'Fred';
l_employee.lastname := 'Bloggs';
-
8/14/2019 3 - PLSQL for Beginners
7/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 7
PL/ SQL Records & Tables
Assigning Records
You can assign one record to another so long as all
the elements in both records are exactly the same,
for example:-
DECLARE
TYPE t_record IS RECORD
( col1 NUMBER, col2 VARCHAR2(10) );
l_record1 t_record;
l_record2 t_record;
BEGIN
l_record1.col1 := 10;
l_record1.col2 := 'Test';
l_record2 := l_record1;
END;
Records can also be used as arguments in
procedures and functions, for example:-
CREATE OR REPLACE PROCEDURE print_dept
(p_dept_rec dept%ROWTYPE)
IS
BEGIN
DBMS_OUTPUT.put_line(p_dept_rec.deptno);
DBMS_OUTPUT.put_line(p_dept_rec.deptno);
DBMS_OUTPUT.put_line(p_dept_rec.deptno);
END;
The above procedure could be invoked with:-
DECLARE
l_rec dept%ROWTYPE;
BEGIN
SELECT * INTO l_rec
FROM dept
WHERE deptno = 10;
print_dept(l_rec);END;
-
8/14/2019 3 - PLSQL for Beginners
8/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 8
PL/ SQL Records & Tables
Creating Tables
A PL/SQL table is very similar to an array found in
most third generation languages. Before a table can
be used, you need to declare a new datatype that is
of type table, you do this with the TYPE statement
in a similar way as you create records. The syntax
ofTYPE in this case is:-
TYPE table-name IS TABLE OF type
INDEX BY BINARY_INTEGER;
Where table-name can be any valid identifier and
type is any valid datatype, including any newdatatypes you have created, such as a record. So,
to declare a table to hold the names of employees
you might:-
TYPE t_names IS TABLE OF emp.ename%TYPE
INDEX BY BINARY_INTEGER;
The INDEX BY specifies how the records on the
table will be indexed, in most cases, this should be
BINARY_INTEGER (though this is not required as of
Oracle8)
-
8/14/2019 3 - PLSQL for Beginners
9/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 9
PL/ SQL Records & Tables
Tables
Once your new table type is declared, you must
declare a variable of the new type, for example:-
names_tab t_names;
The above code will create a new variable called
names_tab of type t_names. You can now use the
table names_tab.
You access individual rows on a PL/SQL table by
using a table index (reference/subscript), similar to
an array subscript. The index should appear
immediately after the table name, for example, to
set the elements of record one in the names_tab
table:-
names_tab(1).empno := 10;
names_tab(1).ename := 'Fred';
The subscript can be any valid number that can be
represented by a binary integer.
-
8/14/2019 3 - PLSQL for Beginners
10/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 10
PL/ SQL Records & Tables
Tables
Here is another example of a less complex table,
this time it is a table of a scalar datatype:-
DECLARE
TYPE t_names IS TABLE OF VARCHAR2(10)
INDEX BY BINARY_INTEGER;
names_tab t_names;BEGIN
names_tab(-10) := 'Fred';
names_tab(0) := 'John';
names_tab(250) := 'Richard';
END;
The table in memory will now look as follows:-
Index Value-10 Fred
0 John
250 Richard
Memory has only been allocated for 3 rows, this is
very much unlike arrays. To set the value of the
250'th row in an array, all elements preceding itmust exist. Nor can an array have a negative
subscript. PL/SQL tables grow dynamically in size as
ou create rows ver much like a database table.
-
8/14/2019 3 - PLSQL for Beginners
11/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 11
PL/ SQL Records & Tables
Tables
If you attempt to reference a row that has not
already been created in a PL/SQL table, then an
exception is raised, for example:-
DECLARE
TYPE t_names IS TABLE OF VARCHAR2(10)
INDEX BY BINARY_INTEGER;
names_tab t_names;
BEGIN
names_tab(0) := 'Fred';
names_tab(1) := 'John';
names_tab(2) := 'Richard';
DBMS_OUTPUT.put_line(names_tab(3));
END;
The above code will fail with the following error:-
ORA-01403: no data found
It will failed because in the line which displays a
value (DBMS_OUTPUT), we are referencing a row
which does not yet exist. You have to handle the
error in a similar fashion as you would for a failing
SELECT statement.
-
8/14/2019 3 - PLSQL for Beginners
12/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 12
PL/ SQL Records & Tables
Tables
Several table attributes exist which allow you to
easily work with tables:-
Attribute Type Returned DescriptionCOUNT NUMBER Returns the number of rows
in the table
DELETE N/A Delete a row from a tableEXISTS BOOLEAN Return TRUE if the specified
row exists, FALSE otherwiseFIRST BINARY_INTEGER Returns the index of the first
row in the tableLAST BINARY_INTEGER Returns the index of the last
row in the tableNEXT BINARY_INTEGER Returns the index of the next
row after a specified rowPRIOR BINARY_INTEGER Returns the index of the
previous row after a specifiedrow
Lets take a quick look at each of these attributes.
-
8/14/2019 3 - PLSQL for Beginners
13/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 13
PL/ SQL Records & Tables
Tables
COUNT
This will return the number of rows in the table.
DECLARE
TYPE t_table IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
number_tab t_table;
l_rows NUMBER;
BEGIN
number_tab(1) := 10;
number_tab(10) := 20;
number_tab(87) := 5;
number_tab(2500) := 100;
l_rows := number_tab.COUNT;
END;
In the above code, l_rows will be set to 4.
-
8/14/2019 3 - PLSQL for Beginners
14/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 14
PL/ SQL Records & Tables
Tables
DELETE
This is used to remove rows from a table.
DECLARE
TYPE t_table IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
number_tab t_table;
BEGIN
number_tab(1) := 10;
number_tab(10) := 20;
number_tab(87) := 5;
number_tab(2500) := 100;
number_tab.DELETE(87);
END;
DELETE can be used in three ways:-
table.DELETE; will remove all rows
table.DELETE(x); remove row i.
table.DELETE(x,y); remove rows i through y.
-
8/14/2019 3 - PLSQL for Beginners
15/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 15
PL/ SQL Records & Tables
Tables
EXISTS
This is used to check whether a specified row exists
or not.
DECLARE
TYPE t_table IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
number_tab t_table;
BEGIN
number_tab(1) := 10;
number_tab(10) := 20;
number_tab(87) := 5;
number_tab(2500) := 100;
IF number_tab.EXISTS(10) THENDBMS_OUTPUT.put_line('Row 10 Found');
END IF;
IF NOT number_tab.EXISTS(100) THENDBMS_OUTPUT.put_line('Row 100 not found');
END IF;
END;
-
8/14/2019 3 - PLSQL for Beginners
16/30
-
8/14/2019 3 - PLSQL for Beginners
17/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 17
PL/ SQL Records & Tables
Tables
NEXTandPRIOR
These allow you to find the index of the next or
previous row in a table based on a specified index.
They allow you to easily move through a table,
processing all rows.
DECLARE
TYPE t_table IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
number_tab t_table;
l_index BINARY_INTEGER;
BEGIN
number_tab(1) := 10;
number_tab(10) := 20;
number_tab(87) := 5;number_tab(2500) := 100;
-- Starting point in table, the first row
l_index := number_tab.FIRST;
LOOP
DBMS_OUTPUT.put_line(number_tab(l_index));
-- End loop when at last row
EXIT WHEN l_index = number_tab.LAST;
-- Get index of next row
l_index := number_tab.NEXT(l_index);
END LOOP;
END;
In the above code, l_index is set to the next row
in the table so long as it is not equal to the last row.
-
8/14/2019 3 - PLSQL for Beginners
18/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 18
PL/ SQL Records & Tables
Tables
PL/SQL are generally very much under-used. They
are very powerful constructs and greatly enhance
the functionality of PL/SQL.
Many programs need to have some kind of
temporary storage area, normally used to hold
intermediate data which needs to be processed in
some way, a great deal of developers create this
temporary storage using database tables, while this
offers some advantages, such as the ability to re-
start a failed process from where it last was, PL/SQL
tables offer advantages too; such a vastly increased
performance, PL/SQL tables are much faster to work
with than database tables, as everything is done in
memory. You also have the advantage of not having
to create and maintain a temporary table. The only
real disadvantage is slightly more complex code.
Use PL/SQL tables wherever possible!!.
-
8/14/2019 3 - PLSQL for Beginners
19/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 19
Host File AccessUTL_FILE
-
8/14/2019 3 - PLSQL for Beginners
20/30
-
8/14/2019 3 - PLSQL for Beginners
21/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 21
Host File Access
UTL_FILE
UTL_FILE is a server side package for writing to
host files on the server, there is another package,
TEXT_IO, which is client side and it not discussed in
this document.
UTL_FILE has the following functions and
procedures:-
FOPEN Used to open a file
FCLOSE Used to closed a file
FCLOSE_ALL Close all open filesIS_OPEN Check if a file is open
FFLUSH Output from UTL_FILE
buffered, this procedure is usedto ensure the buffer has beenwritten to the file.
PUT Write to file
PUT_LINE Write to file
NEW_LINE Write to file
PUTF Write to file
GET_LINE Read from a file
-
8/14/2019 3 - PLSQL for Beginners
22/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 22
Host File Access
UTL_FILE
FOPEN
Use this function to open a file. FOPEN is defined
as:-
FUNCTION fopen( path IN VARCHAR2
, filename IN VARCHAR2
, mode IN VARCHAR2)RETURN FILE_TYPE;
PATH the directory containing the file
FILENAME the actual filename
MODE the Open Mode, this can be one of:-
'r' : Read from file
'w' : Write to file
'a' : Append to file
The return type is the File Handle which is used to
reference the open file is other functions. It's type is
UTL_FILE.file_type.
DECLARE
l_handle UTL_FILE.file_type;
BEGIN
l_handle := UTL_FILE.fopen( '/u01/app', 'my_file.dat', 'r');
. . .
The above code will open the file
/u01/app/my_file.dat for reading.
-
8/14/2019 3 - PLSQL for Beginners
23/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 23
Host File Access
UTL_FILE
FCLOSE & FCLOSE_ALL
Use these procedures to close open files. Closing
files free's up any resources used by UTL_FILE.
DECLARE
l_handle UTL_FILE.file_type;
BEGINl_handle := UTL_FILE.fopen( '/u01/app'
, 'my_file.dat'
, 'r');
. . .
UTL_FILE.fclose(l_handle);
or
UTL_FILE.fclose_all;
END;
Generally, always use FCLOSE(handle) rather
than FCLOSE_ALL. FCLOSE_ALL is useful in
exception handlers, where you may not know which
files are open, it can be used before a program ends
to ensure all resources are freed.
Notice that FCLOSE takes a file handle from a
previous FOPEN call, whereas FCLOSE_ALL takes
no arameters.
-
8/14/2019 3 - PLSQL for Beginners
24/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 24
Host File Access
UTL_FILE
IS_OPEN & FFLUSH
The IS_OPEN function is used to determine if a file
is open. It takes as its argument the file handle and
it returns TRUE if the file is open, otherwise FALSE
is returned.
BEGIN
IF UTL_FILE.is_open(l_handle)UTL_FILE.fclose(l_handle);
END IF;END;
The above code will only attempt to close a file it it
is already open.
FFLUSH is used to ensure the output buffer has
been written to the file. It is wise to flush the buffer
before a program ends to ensure all data is written.
Be aware that flushing after every write to a file can
impact on performance.
For example:-
UTL_FILE.fflush(l_handle);
-
8/14/2019 3 - PLSQL for Beginners
25/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 25
Host File Access
UTL_FILE
PUT & PUT_LINE
This procedure is used to write data to a file.
UTL_FILE.put(handle,buffer);
Where handle is the handle of an already open file
and buffer the string to be written.
PUT does not append a newline character to the
buffer; you should use PUT_LINE or NEW_LINE for
this. PUT_LINE is almost the same as PUT except
that it automatically add's a newline character to the
end of buffer.
Example
DECLARE
l_handle UTL_FILE.file_type;
BEGIN
l_handle := UTL_FILE.fopen( '/u01/app'
, 'my_file.dat'
, 'w');
UTL_FILE.put(l_handle,'This line is written');
UTL_FILE.fclose(l_handle);
END;
-
8/14/2019 3 - PLSQL for Beginners
26/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 26
Host File Access
UTL_FILE
PUTF
This procedure is used to write data to a file.
UTL_FILE.putf(handle,format,arg1,arg2,arg3,arg4,arg5);
Where handle is the handle of an already open file.
The parameters arg1 to arg5 are optional and are
string that are written to the file in a format
specified by format.
format is any string of text which can contain
special codes used to print the strings in arg1 to
arg5. The %s code is replaced in the string with is
corresponding arg parameter. You can also use the
code \n to add a newline character. It is similar to
C's printf function.
Example
DECLAREl_handle UTL_FILE.file_type;
BEGIN
l_handle := UTL_FILE.fopen( '/u01/app'
, 'my_file.dat'
, 'w');
UTL_FILE.putf(l_handle,'arg1=%s\n','Fred');
UTL_FILE.fclose(l_handle);
END;
-
8/14/2019 3 - PLSQL for Beginners
27/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 27
Host File Access
UTL_FILE
NEW_LINE
This procedure writes one or more newline
characters to the file.
UTL_FILE.new_line(handle,lines);
Where handle is the handle of an already open file
and lines is the number of newline characters to be
written.
-
8/14/2019 3 - PLSQL for Beginners
28/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 28
Host File Access
UTL_FILE
GET_LINE
This procedure is used to read from a file.
UTL_FILE.get_line(handle,buffer);
Where handle is the handle of an already open file
and buffer is where the text retreived will be stored.
GET_LINE reads one full line from the file but it
does include the newline character.
Example
DECLAREl_handle UTL_FILE.file_type;
l_buffer VARCHAR2(500);
BEGIN
l_handle := UTL_FILE.fopen( '/u01/app'
, 'my_file.dat'
, 'r');
UTL_FILE.get_line(l_handle,l_buffer);
UTL_FILE.fclose(l_handle);
END;
The above example opens a file and reads a single
line from it before closing the file.
-
8/14/2019 3 - PLSQL for Beginners
29/30
Training GuidePL/SQL for Beginners - Supplement
Copyright 1999 2004 ApplTop Solutions Limited 29
Host File Access
UTL_FILE - Exceptions
There are many things that can go wrong when
working with host file, the directory may not exist,
the disk maybe fulletc. PL/SQL provides a way of
ensuring your program handles these problems
gracefully by providing a number of predefined
UTL_FILE exceptions. These exceptions are
handled like any other exceptions, within the
exception handler in your code. The exceptions are
listed below:-
Exception Raised When Raised ByINVALID_PATH Directory or filename is invalid FOPEN
INVALID_MODE Invalid open mode specified FOPEN
INVALID_FILEHANDLE File handle does not point to anopen file
FCLOSE,GET_LINE,PUT,PUTF,PUT_LINE,NEW_LINE,FFLUSH
INVALID_OPERATION Attempt to read a file open for writeor visa-versa. Could also be causedby some operating system problemsuch as file permissions
GET_LINE,PUT,PUTF,PUT_LINE,NEW_LINE,FFLUSH
READ_ERROR Operating system error during readoperation GET_LINE
WRITE_ERROR Operating system error during writeoperation
FCLOSE,PUT,PUTF,PUT_LINE,NEW
_LINE,FFLUSH,FCLOSE_ALL
INTERNAL_ERROR Unspecified internal error All
NO_DATA_FOUND End of file reached during read GET_LINE
VALUE_ERROR Data returned by GET_LINE is toolarge for buffer
GET_LINE
-
8/14/2019 3 - PLSQL for Beginners
30/30
Training GuidePL/SQL for Beginners - Supplement
Host File Access
UTL_FILE - A Complete Example
Below is a prodedure that can be used to dump out
the contents of the dept table to a file.
CREATE OR REPLACE PROCEDURE dump_dept
IS
CURSOR dept_cur
IS
SELECT deptno, dname
, loc
FROM dept;
l_handle UTL_FILE.file_type;
l_path VARCHAR2(50) := '/u01/app';
l_filename VARCHAR2(20) := 'dept.dat';
l_record VARCHAR2(200);
BEGIN
-- Open file
l_handle := UTL_FILE.fopen( l_path, l_filename
, 'w');
-- Get all dept rows
FOR r_dept IN dept_cur
LOOP
l_record := TO_CHAR(r_dept.deptno)||'|'||
r_dept.dname||'|'||
TO_CHAR(r_dept.loc);
-- Write row to file
UTL_FILE.put_line(l_handle,l_record);
END LOOP;
UTL_FILE.fflush(l_handle);
UTL_FILE.fclose(l_handle);
EXCEPTION
WHEN UTL_FILE.invalid_path THEN
DBMS_OUTPUT.put_line('Invalid Path');
WHEN UTL_FILE.write_error THEN
DBMS_OUTPUT.put_line('Write Error');
END;