Vous êtes sur la page 1sur 15

PL/SQL User Defined Types

Record and Table


Please use speaker notes for
additional information!
Records

A record is defined as a composite data structure because it is


composed of multiple elements (components).
The record does not have its own value because it is viewed
as a structure to store and access the individual components
each of which has its own value.
In Oracle there are three types of RECORDS: table-based,
cursor-based and programmer-defined. While their uses vary,
they have the same internal structure. Every record is
composed of one or more elements/fields.
Implicit cursor

Implicit cursors are used by PL/SQL blocks whenever an SQL


statement is executed if there is not an existing explicit cursor
associated with the statement. The implicit cursor is
automatically setup by Oracle and is not under the control of
the programmer/developer.
Oracle sets up what is know as the context area which contains
the information Oracle needs to process a statement. The
cursor serves as a pointer or handle to the context area.
In PL/SQL the implicit cursor is used to process the DML
statements such as INSERT, DELETE, UPDATE as well as the
SELECT INTO statement.
SQL> SELECT * FROM donor
TYPE - RECORD 2 WHERE idno = 23456;

IDNO NAME STADR CITY ST ZIP DATEFST YRGOAL CONTACT


----- --------------- --------------- ---------- -- ----- --------- --------- ------------
23456 Susan Ash 21 Main St Fall River MA 02720 04-MAR-92 100 Amy Costa
SQL> edit atsd1

SET VERIFY OFF


ACCEPT in_idno PROMPT 'Please enter the donor idno: '
DECLARE
TYPE rec_donor IS RECORD
(rec_id VARCHAR2(5), rec_name VARCHAR2(15), rec_yrgoal NUMBER(7,2));
a_rec_donor rec_donor; -- Note: this declares a variable of the defined type
BEGIN
SELECT idno, name, yrgoal INTO a_rec_donor.rec_id, a_rec_donor.rec_name, a_rec_donor.rec_yrgoal
FROM new_donor WHERE idno = &in_idno;
INSERT INTO some_donor
VALUES(a_rec_donor.rec_id, a_rec_donor.rec_name, a_rec_donor.rec_yrgoal);
END;
/
SET VERIFY ON

SQL> @ atsd1
Please enter the donor idno: 23456

PL/SQL procedure successfully completed.

SQL> SELECT * FROM some_donor;

IDNO NAME YRGOAL


----- --------------- ---------
23456 Susan Ash 100
SQL> SELECT * FROM donor WHERE idno = 11111;
TYPE - RECORD
IDNO NAME STADR CITY ST ZIP DATEFST YRGOAL CONTACT
----- --------------- --------------- ---------- -- ----- --------- --------- ------------
11111 Stephen Daniels 123 Elm St Seekonk MA 02345 03-JUL-98 500 John Smith

SQL> edit atsd2


SET VERIFY OFF
ACCEPT in_idno PROMPT 'Please enter the donor idno: '
DECLARE
TYPE rec_donor IS RECORD
(rec_id VARCHAR2(5), rec_name VARCHAR2(15), rec_yrgoal NUMBER(7,2));
a_rec_donor rec_donor; -- Note: this declares a variable of the defined type
BEGIN
SELECT idno, name, yrgoal INTO a_rec_donor
FROM new_donor WHERE idno = &in_idno;
INSERT INTO some_donor
VALUES(a_rec_donor.rec_id, a_rec_donor.rec_name, a_rec_donor.rec_yrgoal);
END;
/
SET VERIFY ON

SQL> @atsd2
Please enter the donor idno: 11111

PL/SQL procedure successfully completed.

SQL> SELECT * FROM some_donor;

IDNO NAME YRGOAL


----- --------------- ---------
23456 Susan Ash 100
11111 Stephen Daniels 500
TYPE - RECORD

SQL> edit atsd2


SET VERIFY OFF
ACCEPT in_idno PROMPT 'Please enter the donor idno: '
DECLARE
TYPE rec_donor IS RECORD
(rec_id VARCHAR2(5), rec_name VARCHAR2(15), rec_yrgoal NUMBER(7,2));
a_rec_donor rec_donor; -- Note: this declares a variable of the defined type
BEGIN
/*This version does not work because of a_rec_donor in the VALUES clause */
SELECT idno, name, yrgoal INTO a_rec_donor
FROM new_donor WHERE idno = &in_idno;
INSERT INTO some_donor
VALUES(a_rec_donor);
END;
/
SET VERIFY ON

SQL> @ atsd2a
Please enter the donor idno: 33333
VALUES(a_rec_donor);
*
ERROR at line 10:
ORA-06550: line 10, column 11:
PLS-00382: expression is of wrong type
ORA-06550: line 9, column 4:
PL/SQL: SQL Statement ignored
ROWTYPE SQL> DESC some_donor
Name Null? Type
------------------------------- -------- ----
IDNO VARCHAR2(5)
NAME VARCHAR2(15)
YRGOAL NUMBER(7,2)

SQL> edit atsd4

SET VERIFY OFF


ACCEPT in_idno PROMPT 'Please enter the donor idno: '
DECLARE
v_donor some_donor%ROWTYPE;
BEGIN
SELECT idno, name, yrgoal INTO v_donor
FROM new_donor WHERE idno = &in_idno;
INSERT INTO some_donor
VALUES(v_donor.idno, v_donor.name, v_donor.yrgoal);
END;
/
SET VERIFY ON
ROWTYPE

SQL> SELECT * FROM some_donor;

IDNO NAME YRGOAL


----- --------------- ---------
23456 Susan Ash 100
11111 Stephen Daniels 500

SQL> @ atsd4
Please enter the donor idno: 22222

PL/SQL procedure successfully completed.

SQL> SELECT * FROM some_donor;

IDNO NAME YRGOAL


----- --------------- ---------
23456 Susan Ash 100
11111 Stephen Daniels 500
22222 Carl Hersey
TABLES

PL/SQL tables are the answer to the need for an


array structure. An array is basically a temporary
table in memory available during the session. They
are not database tables!
The PL/SQL table is indexed by a binary integer.
To declare a PL/SQL table: first define the table
structure using TYPE IS TABLE and then once
the type has been created, you can declare the actual
table.
TYPE..TABLE

SQL> edit table1

SET SERVEROUTPUT ON
DECLARE
TYPE t_table1 IS TABLE OF VARCHAR2(12)
INDEX BY BINARY_INTEGER;
v_table_var t_table1;
v_count_result NUMBER;
BEGIN
v_table_var(5) := 'Fifth week';
v_table_var(2) := 'Second week';
v_table_var(12) := 'Twelfth week';
v_table_var(6) := 'Sixth week';
v_count_result:= v_table_var.COUNT;
dbms_output.put_line('The count is: '||v_count_result);
END;
/
SET SERVEROUTPUT OFF

SQL> @ table1
The count is: 4

PL/SQL procedure successfully completed.


TYPE..TABLE

SQL> edit table1a

SET SERVEROUTPUT ON
DECLARE
Output:
TYPE t_table1 IS TABLE OF VARCHAR2(12)
INDEX BY BINARY_INTEGER;
v_table_var t_table1; SQL> @ table1a
v_count_result NUMBER; The current place is: 2
v_place NUMBER; The current place is: 5
BEGIN The current place is: 6
v_table_var(5) := 'Fifth week'; The current place is: 12
v_table_var(2) := 'Second week'; The count is: 4
v_table_var(12) := 'Twelfth week';
v_table_var(6) := 'Sixth week';
v_place := v_table_var.FIRST;
FOR x IN 1..4 LOOP
dbms_output.put_line('The current place is: ' || v_place);
v_place := v_table_var.NEXT(v_place);
END LOOP;
v_count_result:= v_table_var.COUNT;
dbms_output.put_line('The count is: '||v_count_result);
END;
/
SET SERVEROUTPUT OFF
TYPE..TABLE SQL> @table2
Enter value for in_num: 5
old 6: v_num NUMBER :=&in_num;
new 6: v_num NUMBER :=5;
SQL> edit table2
The count is: 4
SET SERVEROUTPUT ON The record exists
DECLARE
TYPE t_table1 IS TABLE OF VARCHAR2(12) PL/SQL procedure successfully completed.
INDEX BY BINARY_INTEGER;
v_table_var t_table1;
v_count_result NUMBER;
v_num NUMBER :=&in_num;
BEGIN
v_table_var(5) := 'Fifth week';
v_table_var(2) := 'Second week';
v_table_var(12) := 'Twelfth week';
v_table_var(6) := 'Sixth week';
v_count_result:= v_table_var.COUNT;
dbms_output.put_line('The count is: '||v_count_result);
IF v_table_var.EXISTS(v_num) THEN
dbms_output.put_line('The record exists');
ELSE
dbms_output.put_line('The record does not exist');
END IF;
END; SQL> @ table2
/ Enter value for in_num: 8
SET SERVEROUTPUT OFF old 6: v_num NUMBER :=&in_num;
new 6: v_num NUMBER :=8;
The count is: 4
The record does not exist

PL/SQL procedure successfully completed.


TABLES
I am starting out with an input area which I assign the value of South Shore MA. My goal is
to search the table until I find a match. To do this, I first set up the table and then I assigned
values to the table. Finally I looped through the table displaying my progress until a match
was found. When a match is found I exit the loop and display the match.
SQL> edit areacodett

SET SERVEROUTPUT ON
DECLARE
input_area VARCHAR2(20) :='South Shore MA';
TYPE t_areacode_type IS TABLE OF VARCHAR2(20) Output:
INDEX BY BINARY_INTEGER;
v_area t_areacode_type; SQL> @ areacodett
v_index NUMBER; Rhode Island 401
BEGIN Southeastern MA 508
v_area(508) := 'Southeastern MA'; Boston MA 617
v_area(617) := 'Boston MA'; South Shore MA 781
v_area(781) := 'South Shore MA'; Match: South Shore MA 781
v_area(401) := 'Rhode Island';
v_area(999) := 'region not found';
v_index := v_area.FIRST;
LOOP
DBMS_OUTPUT.PUT_LINE(v_area(v_index) ||' ' || v_index);
EXIT WHEN v_index = v_area.LAST OR v_area(v_index) = input_area;
v_index := v_area.NEXT(v_index);
END LOOP;
DBMS_OUTPUT.PUT_LINE('Match: ' || v_area(v_index) ||' ' || v_index);
END;
/
SET SERVEROUTPUT OFF
TYPE..TABLE
In this example, processing stops when Boston is encountered.
This causes the EXIT because v_area(v_index) = input_area.

SQL> edit areacodett

SET SERVEROUTPUT ON
DECLARE
input_area VARCHAR2(20) :=Boston MA';
TYPE t_areacode_type IS TABLE OF VARCHAR2(20)
INDEX BY BINARY_INTEGER; Output:
v_area t_areacode_type;
v_index BINARY_INTEGER;
SQL> @ areacodett
BEGIN Rhode Island 401
v_area(508) := 'Southeastern MA'; Southeastern MA 508
v_area(617) := 'Boston MA'; Boston MA 617
v_area(781) := 'South Shore MA'; Match: Boston MA 617
v_area(401) := 'Rhode Island';
v_area(999) := 'region not found';
v_index := v_area.FIRST;
LOOP
DBMS_OUTPUT.PUT_LINE(v_area(v_index) ||' ' || v_index);
EXIT WHEN v_index = v_area.LAST OR v_area(v_index) = input_area;
v_index := v_area.NEXT(v_index);
END LOOP;
DBMS_OUTPUT.PUT_LINE('Match: ' || v_area(v_index) ||' ' || v_index);
END;
/
SET SERVEROUTPUT OFF
TYPETABLE
In this example, there is no match for XXX MA, so when all
elements of the array have been completed, processing ends.
The LAST attribute is what makes this work. When v_index
which keeps getting incremented to the NEXT number finall
SQL> edit areacodett equals the last number in the table, processing ends.

SET SERVEROUTPUT ON
DECLARE
input_area VARCHAR2(20) :=XXX MA';
TYPE t_areacode_type IS TABLE OF VARCHAR2(20) Output:
INDEX BY BINARY_INTEGER;
v_area t_areacode_type; SQL> @ areacodett
v_index NUMBER; Rhode Island 401
BEGIN Southeastern MA 508
v_area(508) := 'Southeastern MA'; Boston MA 617
v_area(617) := 'Boston MA'; South Shore MA 781
v_area(781) := 'South Shore MA'; region not found 999
v_area(401) := 'Rhode Island'; Match: region not found 999
v_area(999) := 'region not found';
v_index := v_area.FIRST;
LOOP
DBMS_OUTPUT.PUT_LINE(v_area(v_index) ||' ' || v_index);
EXIT WHEN v_index = v_area.LAST OR v_area(v_index) = input_area;
v_index := v_area.NEXT(v_index);
END LOOP;
DBMS_OUTPUT.PUT_LINE('Match: ' || v_area(v_index) ||' ' || v_index);
END;
/
SET SERVEROUTPUT OFF

Vous aimerez peut-être aussi