Previous | Table of Contents | Next

Page 274

Listing 10.16. continued

 13                   to_char(ER_Patient.Body_Temp_Deg_F));
 14
 14  end;
 15  /
ER_Patient.Body_Temp_Deg_F: 98.6

However, you cannot assign one %ROWTYPE variable to another %ROWTYPE variable if the two variables don't point to the same database table, even if the two tables are identical.

Listing 10.17. %ROWTYPE variables based on different tables cannot be assigned to one another.

SQL> create table Identical_Patient as
  2  select * from Patient;
Table created.
SQL> set serveroutput on
SQL>
SQL> declare
  2
  2  New_Patient   Patient%ROWTYPE;
  3  ER_Patient    Identical_Patient%ROWTYPE;
  4
  4  begin
  5
  5  dbms_output.enable;
  6
  6  select *
  7  into New_Patient
  8  from Patient
  9  where
 10  Patient_ID = `ZZ0123';
 11
 11  ER_Patient := New_Patient;
 12
 12  dbms_output.put_line(`ER_Patient.Body_Temp_Deg_F: ` ||
 13                       to_char(ER_Patient.Body_Temp_Deg_F));
 14
 14  end;
 15  /
declare
 *
ERROR at line 1:
ORA-06550: line 11, column 15:
PLS-00382: expression is of wrong type
ORA-06550: line 11, column 1:
PL/SQL: Statement ignored

Page 275

More Complex Datatypes: Tables and Records

PL/SQL supports two additional composite datatypes: tables and records. Each of these objects is first declared as a datatype, and then the actual PL/SQL table or record is declared based upon the specified datatype.

You can think of a PL/SQL table as an array: it consists of a single field. Also, you don't declare an upper limit on the number of elements that a PL/SQL table can contain; its size is dynamic.

NEW TERM
A PL/SQL table is a collection of elements of the same type, ordered by an index number.

NOTE
It is unfortunate that Oracle chose to apply the label table to a structure that is more appropriately described as an array. A PL/SQL table, unlike a database table, is composed of a single column. As with an array, the values of a PL/SQL table are accessed by an index. Just remember that a PL/SQL table and a database table are two distinct objects with very specific characteristics and uses.

A user-defined record offers more flexibility than the %ROWTYPE designation. You should consider using a user-defined record when both of the following conditions are true:

The following section delves into the use of PL/SQL tables.

TIP
If you declare a user-defined record type that is associated with a database table, use the %TYPE designation for each field that mirrors a column in the database table. It reduces the effort needed to maintain PL/SQL code in response to those inevitable database changes.

Declaring PL/SQL Tables

A type for a PL/SQL table is declared using the following syntax:

TYPE type-name IS TABLE OF
table-name.column-name%TYPE
INDEX BY BINARY_INTEGER;

Page 276

The variables are defined as follows:

type-name is the name of the declared type.

table-name.column-name specifies the column whose datatype is the base type for type-name.

After you've declared a PL/SQL table type, you can then declare variables based on that type. For example, in Listing 10.18, which contains an anonymous PL/SQL block, Class_ID_Tab is declared as a table of the column Class_ID in the Class table. A cursor FOR LOOP selects each Class_ID from the Class table and assigns it to an element in Class_ID_Tab. The example shown in Listing 10.18 was performed using SQL Worksheet.

Listing 10.18. Using a PL/SQL table.

SQLWKS> set serveroutput on
Server Output                   ON
SQLWKS> declare
     2>
     3> type Class_ID_Type is table of Class.Class_ID%TYPE
     4> index by binary_integer;
     5>
     6> Class_ID_Tab      Class_ID_Type;
     7> i                 binary_integer := 0;
     8> final_count       binary_integer;
     9>
    10> begin
    11>
    12> dbms_output.enable;
    13>
    14> for Class_ID_Rec in (select Class_ID from Class) loop
    15>
    16>   i := i + 1;
    17>   Class_ID_Tab(i) := Class_ID_Rec.Class_ID;
    18>
    19> end loop;
    20>
    21> final_count := i;
    22>
    23> for i in 1..final_count loop
    24>
    25>   dbms_output.put_line(`Class_ID_Tab(` || to_char(i) || `) = ` ||
    26>                        Class_ID_Tab(i));
    27> end loop;
    28>
    29> end;
    30> /
Statement processed.
Class_ID_Tab(1) = 104200
Class_ID_Tab(2) = 104500
Class_ID_Tab(3) = 109100
Class_ID_Tab(4) = 120200

Page 277

Class_ID_Tab(5) = 110300
Class_ID_Tab(6) = 108300
Class_ID_Tab(7) = 108400
Class_ID_Tab(8) = 108600
Class_ID_Tab(9) = 103400
Class_ID_Tab(10) = 103600

You can pass a PL/SQL table as an argument to a procedure or function. Along with the PL/SQL table, you'll also want to pass a BINARY_INTEGER variable that indicates the number of elements in the PL/SQL table. Listing 10.19 illustrates an example of a procedure that returns a PL/SQL table containing Course_IDs for which the additional fees exceed $50.

Listing 10.19. Returning a PL/SQL table.

SQLWKS> declare
     2>
     3> type Course_ID_Type is table of Course.Course_ID%TYPE
     4>   index by binary_integer;
     5> Course_ID_Tab   Course_ID_Type;
     6>
     7> i                 binary_integer := 0;
     8> Total_Number      binary_integer;
     9>
    10> procedure Get_Course_IDs (Num_Rows out binary_integer,
    11>                           Course_ID_Table out Course_ID_Type) is
    12>
    13> i   binary_integer := 0;
    14>
    15> begin
    16>
    17> for Course_ID_Rec in (select Course_ID from Course
    18>       where Additional_Fees > 50) loop
    19>
    20>   i := i + 1;
    21>   Course_ID_Table(i) := Course_ID_Rec.Course_ID;
    22>
    23> end loop;
    24>
    25> Num_Rows := i;
    26>
    27> end Get_Course_IDs;
    28>
    29> --  Main block.
    30>
    31> begin
    32>
    33> dbms_output.enable;
    34>
    35> Get_Course_IDs (Total_Number, Course_ID_Tab);
    36>
    37> for i in 1..Total_Number loop
    38>   exit when Course_ID_Tab(i) = NULL;
	
                                                  continues              

Page 278

Listing 10.19. continued

    39>   dbms_output.put_line(`Course_ID_Tab(` || to_char(i) ||
    40>                      `) = ` || Course_ID_Tab(i));
    41> end loop;
    42>
    43> end;
    44> /

Statement processed.
Course_ID_Tab(1) = 101
Course_ID_Tab(2) = 189
Course_ID_Tab(3) = 101
Course_ID_Tab(4) = 178
Course_ID_Tab(5) = 177
Course_ID_Tab(6) = 174
Course_ID_Tab(7) = 181
Course_ID_Tab(8) = 501
ANALYSIS
In Listing 10.19, the first line begins with the declaration section of an anonymous block. The type Course_ID_Type is declared in line 3. A procedure, Get_Course_IDs, is declared beginning on line 10. In line 13, the index for the PL/SQL table Course_ID_Table is initialized to 0. The execution section of the anonymous block begins on line 31. The procedure Get_Course_IDs is invoked on line 35 in the execution section of the anonymous block.

NOTE
PL/SQL doesn't restrict the range of the PL/SQL table index; you could start at _100, 0, 1, or any other number that is appropriate.

Declaring User-Defined Records

The process for using a user-defined record is much like that of a PL/SQL table: you define a datatype for the record and then declare variables based on the new type.

The following is the syntax for declaring a record type:

TYPE type-name IS RECORD
(field-name field-datatype [NOT NULL] [initial-value],
...
 field-name field-datatype [NOT NULL] [initial-value]);

The variables for declaring a record type are defined as follows:

type-name is the name of the declared record type.

field-name is the name of the field and subject to PL/SQL variable-name restrictions.

Previous | Table of Contents | Next

Используются технологии uCoz