Create the following PL/SQL script: -- ch15_1a.sql, version 1.0 SET SERVEROUTPUT ON DECLARE CURSOR course_cur ISSELECT descriptionFROM course; TYPE course_type IS TABLE OF course.descrip
Trang 1DID YOU KNOW?
What is the difference between a NULL collection and an empty collection? If a collection has notbeen initialized, referencing its individual elements causes the following error:
TYPE integer_type IS TABLE OF INTEGER;
integer_tab integer_type := integer_type();
Trang 2EXTEND increases the size of a collection.
DELETE deletes either all elements, elements in the specified range, or a particular element from a collection Note that PL/SQL keeps placeholders of the deleted elements.
FIRST and LAST return subscripts of the first and last elements of a collection Note that
if the first elements of a nested table are deleted, the FIRST method returns a value greater than 1 If elements have been deleted from the middle of a nested table, the LAST method returns a value greater than the COUNT method.
PRIOR and NEXT return subscripts that precede and succeed a specified collection subscript.
TRIM removes either one or a specified number of elements from the end of a collection Note that PL/SQL does not keep placeholders for the trimmed elements.
BY THE WAY
EXTEND and TRIM methods cannot be used with index-by tables
Consider the following example, which illustrates the use of various collection methods:
Trang 3FOR EXAMPLE(continued)
Trang 4The first line of the output
evaluates to TRUE as well.
The second and third lines of the output
LAB 15.1
PL/SQL Tables
325
Trang 5▼ L A B 1 5 1 E X E R C I S E S
This section provides exercises and suggested answers, with discussion related to how those answersresulted The most important thing to realize is whether your answer works You should figure out theimplications of the answers and what the effects are of any different answers you may come up with
15.1.1 Use Associative Arrays
In this exercise, you learn more about associative arrays
Create the following PL/SQL script:
ch15_1a.sql, version 1.0
SET SERVEROUTPUT ON
DECLARE
CURSOR course_cur ISSELECT descriptionFROM course;
TYPE course_type IS TABLE OF course.description%TYPEINDEX BY BINARY_INTEGER;
Answer the following questions, and complete the following tasks:
A) Explain the preceding script
ANSWER:The declaration section of the script defines the associative array type,
course_type This type is based on the column DESCRIPTION of the table COURSE Next, theactual associative array is declared as course_tab
The executable section of the script populates the course_tabtable in the cursor FOR loop.Each element of the associative array is referenced by its subscript,v_counter For each itera-tion of the loop, the value of v_counteris incremented by 1 so that each new description
value is stored in the new row of the associative array
B) Modify the script so that rows of the associative array are displayed on the screen
ANSWER:The script should look similar to the following Changes are shown in bold
ch15_1b.sql, version 2.0
SET SERVEROUTPUT ON
DECLARE
CURSOR course_cur ISSELECT descriptionFROM course;
LAB 15.1
326
Lab 15.1 Exercises
Trang 6TYPE course_type IS TABLE OF course.description%TYPEINDEX BY BINARY_INTEGER;
TYPE course_type IS TABLE OF course.description%TYPEINDEX BY BINARY_INTEGER;
course(2): Intro to Computers
course(3): Intro to Programming
course(4): Structured Programming Techniques
course(5): Hands-On Windows
course(6): Intro to Java Programming
course(7): Intermediate Java Programming
course(8): Advanced Java Programming
course(9): JDeveloper
course(10): Intro to Unix
course(11): Basics of Unix Admin
course(12): Advanced Unix Admin
LAB 15.1
Lab 15.1 Exercises
327
Trang 7course(13): Unix Tips and Techniques
course(14): Structured Analysis
course(15): Project Management
course(16): Database Design
course(17): Internet Protocols
course(18): Java for C/C++ Programmers
course(19): GUI Programming
course(20): Intro to SQL
course(21): Oracle Tools
course(22): PL/SQL Programming
course(23): Intro to Internet
course(24): Intro to the Basic Language
course(25): Operating Systems
course(26): Network Administration
course(27): JDeveloper Lab
course(28): Database System Principles
course(29): JDeveloper Techniques
course(30): DB Programming in Java
PL/SQL procedure successfully completed
C) Modify the script so that only first and last rows of the associative array are displayed on
TYPE course_type IS TABLE OF course.description%TYPEINDEX BY BINARY_INTEGER;
Trang 8course(1): DP Overview
course(30): DB Programming in Java
PL/SQL procedure successfully completed
D) Modify the script by adding the following statements, and explain the output produced:
I) Display the total number of elements in the associative array after it has been populated onthe screen
II) Delete the last element, and display the total number of elements of the associative arrayagain
III) Delete the fifth element, and display the total number of elements and the subscript of thelast element of the associative array again
ANSWER:The script should look similar to the following All changes are shown in bold
ch15_1e.sql, version 5.0
SET SERVEROUTPUT ON
DECLARE
CURSOR course_cur ISSELECT descriptionFROM course;
TYPE course_type IS TABLE OF course.description%TYPEINDEX BY BINARY_INTEGER;
Trang 9Delete the last element of the associative array Display the total number of elements in the associative array course_tab.DELETE(course_tab.LAST);
DBMS_OUTPUT.PUT_LINE ('2 Total number of elements: '||
course_tab.COUNT);
Delete the fifth element of the associative array Display the total number of elements in the associative array Display the subscript of the last element of the associative array
When run, this example produces the following output:
1 Total number of elements: 30
2 Total number of elements: 29
3 Total number of elements: 28
3 The subscript of the last element: 29
PL/SQL procedure successfully completed
First, the total number of elements in the associative array is calculated using the COUNT methodand displayed on the screen Second, the last element is deleted using the DELETE and LAST
methods, and the total number of elements in the associative array is displayed on the screen
again Third, the fifth element is deleted, and the total number of elements in the associative arrayand the subscript of the last element are displayed on the screen
Consider the last two lines of output After the fifth element of the associative array is deleted, theCOUNT method returns the value 28, and the LAST method returns the value 29 Usually, the
values returned by the COUNT and LAST methods are equal However, when an element is deletedfrom the middle of the associative array, the value returned by the LAST method is greater thanthe value returned by the COUNT method, because the LAST method ignores deleted elements
15.1.2 Use Nested Tables
In this exercise, you learn more about nested tables
Complete the following tasks:
A) Modify script ch15_1a.sql, used in Exercise 15.1.1 Instead of using an associative array, use a
LAB 15.1
330
Lab 15.1 Exercises
Trang 10TYPE course_type IS TABLE OF course.description%TYPE;
course_tab course_type := course_type();
B) Modify the script by adding the following statements, and explain the output produced:
I) Delete the last element of the nested table, and then assign a new value to it Execute thescript
II) Trim the last element of the nested table, and then assign a new value to it Execute thescript
TYPE course_type IS TABLE OF course.description%TYPE;
course_tab course_type := course_type();
LAB 15.1
Lab 15.1 Exercises
331
Trang 11TYPE course_type IS TABLE OF course.description%TYPE;
course_tab course_type := course_type();
course_tab(30) := 'New Course';
does not cause any errors
In the current version of the script, the last element of the nested table is removed using the TRIMmethod In this case, PL/SQL does not keep a placeholder of the trimmed element, because theTRIM method manipulates the internal size of a collection As a result, the reference to the
trimmed elements causes a Subscript beyond counterror
C) How would you modify the script created so that no error is generated when a new value is
assigned to the trimmed element?
ANSWER:The script should look similar to the following Changes are shown in bold
ch15_2d.sql, version 4.0
SET SERVEROUTPUT ON
DECLARE
CURSOR course_cur ISSELECT descriptionFROM course;
TYPE course_type IS TABLE OF course.description%TYPE;
course_tab course_type := course_type();
Trang 12collec-course_tab(30) := 'New Course';
does not cause any errors
LAB 15.1
Lab 15.1 Exercises
333
Trang 13LAB 15.2
334
maximum size = 10
10 1 39 57 3
num
(1)
num (2)
num (3)
num (4)
num (5)
In Figure 15.2, the upper bound of a varray is 5, but it can be extended to 6, 7, 8, and so on
up to 10 Therefore, a varray can contain a number of elements, varying from 0 (an empty array)
to its maximum size You will recall that PL/SQL tables do not have a maximum size that must
be specified explicitly.
The general syntax for creating a varray is as follows (the reserved words and phrases in square brackets are optional):
TYPE type_name IS {VARRAY | VARYING ARRAY} (size_limit) OF
element_type [NOT NULL];
varray_name TYPE_NAME;
Trang 14First, a varray structure is defined using the TYPE statement, where type_name is the name of the type that is used in the second step to declare an actual varray Notice that there are two vari- ations of the type, VARRAY and VARYING ARRAY A size_limit is a positive integer literal that specifies the upper bound of a varray As in the case of PL/SQL tables, restrictions apply to
an element_type of a varray These restrictions are listed in the online Oracle help Second, the actual varray is declared based on the type specified in the first step.
Consider the following code fragment:
Similar to nested tables, a varray is automatically NULL when it is declared and must be ized before its individual elements can be referenced Consider a modified version of the example used in the preceding lab Instead of using a nested table, this version uses a varray (changes are highlighted in bold).
initial-FOR EXAMPLE
DECLARE
CURSOR name_cur IS
SELECT last_nameFROM studentWHERE rownum <= 10;
TYPE last_name_type IS VARRAY(10) OF student.last_name%TYPE;
last_name_varray last_name_type := last_name_type();
Trang 15This example produces the following output:
PL/SQL procedure successfully completed
Based on this example, you may realize that the collection methods you saw in the preceding lab can be used with varrays as well Consider the following example, which illustrates the use
of various collection methods when applied to a varray:
FOR EXAMPLE
DECLARE
TYPE varray_type IS VARRAY(10) OF NUMBER;
varray varray_type := varray_type(1, 2, 3, 4, 5, 6);
BEGIN
DBMS_OUTPUT.PUT_LINE ('varray.COUNT = '||varray.COUNT);
DBMS_OUTPUT.PUT_LINE ('varray.LIMIT = '||varray.LIMIT);
DBMS_OUTPUT.PUT_LINE ('varray.FIRST = '||varray.FIRST);
DBMS_OUTPUT.PUT_LINE ('varray.LAST = '||varray.LAST);
Trang 16varray(8) = 4
varray.LAST = 6
PL/SQL procedure successfully completed
The first two lines of output
varray.COUNT = 6
varray.LIMIT = 10
show the results of the COUNT and LIMIT methods, respectively You will recall that the COUNT method returns the number of elements that a collection contains The collection has been initialized to six elements, so the COUNT method returns a value of 6.
The next line of output corresponds to another collection method, LIMIT This method returns the maximum number of elements that a collection can contain It usually is used with varrays only because varrays have an upper bound specified at the time of declaration The collection VARRAY has an upper bound of 10, so the LIMIT method returns a value of 10 When used with nested tables, the LIMIT method returns NULL, because nested tables do not have a maximum size.
The third and fourth lines of the output
varray.FIRST = 1
varray.LAST = 6
show the results of the FIRST and LAST methods.
The fifth and six lines of the output
You cannot use the DELETE method with a varray to remove its elements Unlike PL/SQL tables,
varrays are dense, and using the DELETE method causes an error, as shown in the following example:DECLARE
TYPE varray_type IS VARRAY(3) OF CHAR(1);
LAB 15.2
Varrays
337
Trang 17ORA-06550: line 6, column 4:
PLS-00306: wrong number or types of arguments in call to
'DELETE' ORA-06550: line 6, column 4:
PL/SQL: Statement ignored
L A B 1 5 2 E X E R C I S E S
This section provides exercises and suggested answers, with discussion related to how those answersresulted The most important thing to realize is whether your answer works You should figure out theimplications of the answers and what the effects are of any different answers you may come up with
15.2.1 Use Varrays
In this exercise, you learn more about varrays You will debug the following script, which populates
city_varraywith ten cities selected from the ZIPCODE table and displays its individual elements onthe screen
Create the following PL/SQL script:
ch15_3a.sql, version 1.0
SET SERVEROUTPUT ON
DECLARE
CURSOR city_cur ISSELECT cityFROM zipcodeWHERE rownum <= 10;
TYPE city_type IS VARRAY(10) OF zipcode.city%TYPE;
Trang 18Execute the script, and then answer the following questions and complete the following tasks:
A) What output is printed on the screen? Explain it
ANSWER:The output should look similar to the following:
collec-B) Modify the script so that no errors are returned at runtime
ANSWER:The script should look similar to the following Changes are shown in bold
ch15_3b.sql, version 2.0
SET SERVEROUTPUT ON
DECLARE
CURSOR city_cur ISSELECT cityFROM zipcodeWHERE rownum <= 10;
TYPE city_type IS VARRAY(10) OF zipcode.city%TYPE;
city_varray city_type := city_type();
Trang 19city_varray(9): Oxford
city_varray(10): New Haven
PL/SQL procedure successfully completed
C) Modify the script as follows: Double the size of the varray, and populate the last ten elements withthe first ten elements In other words, the value of the eleventh element should be equal to thevalue of the first element, the value of the twelfth element should be equal to the value of thesecond element, and so forth
ANSWER:The script should look similar to the following Changes are shown in bold
ch15_3c.sql, version 3.0
SET SERVEROUTPUT ON
DECLARE
CURSOR city_cur ISSELECT cityFROM zipcodeWHERE rownum <= 10;
TYPE city_type IS VARRAY(20) OF zipcode.city%TYPE;
city_varray city_type := city_type();
city_varray.EXTEND(1, i);
END LOOP;
FOR i IN 1 20 LOOP DBMS_OUTPUT.PUT_LINE('city_varray('||i||'): '||
city_varray(i));
END LOOP;
END;
In the preceding script, you increase the maximum size of the varray to 20 at the time of the
city_typedeclaration After the first ten elements of the varray are populated, the last ten
elements are populated using the numeric FOR loop and the EXTEND method:
FOR i IN 1 v_counter LOOP
extend the size of varray by 1 and copy the current element to the last element
Trang 20In this loop, the loop counter is implicitly incremented by 1 So for the first iteration of the loop,the size of the varray is increased by 1, and the first element of the varray is copied to the eleventhelement In the same manner, the second element of the varray is copied to the twelfth element,and so forth.
To display all elements of the varray, the DBMS_OUTPUT.PUT_LINE statement has been moved toits own numeric FOR loop that iterates 20 times
When run, this script produces the following output:
city_varray(20): New Haven
PL/SQL procedure successfully completed
LAB 15.2
Lab 15.2 Exercises
341
Trang 21L A B 1 5 3
Multilevel Collections
L A B O B J E C T I V E
After completing this lab, you will be able to
Use multilevel collections
So far you have seen various examples of collections with the element type based on a scalar type, such as NUMBER and VARCHAR2 Starting with Oracle 9i, PL/SQL lets you create collec- tions whose element type is based on a collection type Such collections are called multilevel collections.
Consider the varray of varrays, also called a nested varray, shown in Figure 15.3.
LAB 15.3
342
varray (4) ofinteger
varray (4) ofinteger
varray (4) ofinteger
varray (3) of varray (4) of integer
FIGURE 15.3
A varray of varrays
A varray of varrays consists of three elements, where each element is a varray consisting of four integers To reference an individual element of a varray of varrays, you use the following syntax:varray_name(subscript of the outer varray)(subscript of the inner
varray)
For example, the varray(1)(3) shown in Figure 15.3 equals 6; similarly, varray(2)(1) equals 1.
Trang 22Consider an example based on Figure 15.3:
FOR EXAMPLE
DECLARE
TYPE varray_type1 IS VARRAY(4) OF INTEGER;
TYPE varray_type2 IS VARRAY(3) OF varray_type1;
varray1 varray_type1 := varray_type1(2, 4, 6, 8);
varray2 varray_type2 := varray_type2(varray1);
In the executable portion of the example, you display the values of varray1 on the screen Next, you extend the upper bound of varray2 by 1 and populate its second element as follows:
Trang 2315.3.1 Use Multilevel Collections
In this exercise, you learn more about multilevel collections
Create the following PL/SQL script:
IF i = 1 THENtable_tab1(j) := j;
ELSE
LAB 15.3
344
Lab 15.3 Exercises
Trang 24Complete the following tasks:
A) Execute the preceding script, and explain the output produced
ANSWER:The output should look similar to the following:
PL/SQL procedure successfully completed
The preceding script uses multilevel associative arrays, or an associative array of associative arrays.The declaration portion of the script defines the multilevel associative array table_tab2 Eachrow of this table is an associative array consisting of multiple rows The executable portion of thescript populates the multilevel table using nested numeric FOR loops In the first iteration of theouter loop, the inner loop populates the associative array table_tab1with values 1, 2, and 3and the first row of the multilevel table table_tab2 In the second iteration of the outer loop,the inner loop populates the associative array table_tab1with values 3, 2, and 1 and the
second row of the multilevel table table_tab2
B) Modify the script so that instead of using multilevel associative arrays, it uses a nested table ofassociative arrays
ANSWER:The script should look similar to the following Changes are shown in bold
ch15_4b.sql, version 2.0
SET SERVEROUTPUT ON
DECLARE
TYPE table_type1 IS TABLE OF INTEGER INDEX BY BINARY_INTEGER;
TYPE table_type2 IS TABLE OF TABLE_TYPE1;
ELSEtable_tab1(j) := 4 - j;
LAB 15.3
Lab 15.3 Exercises
345
Trang 25TYPE table_type1 IS VARRAY(3) OF INTEGER;
TYPE table_type2 IS TABLE OF TABLE_TYPE1;
table_tab1 table_type1 := table_type1();
table_tab2 table_type2 := table_type2(table_tab1);
table_tab1andtable_tab2are initialized prior to their use
In the executable portion of the script, the size of table_tab2is incremented using the
EXTEND method, and its individual elements are initialized as follows:
table_tab2(i) := table_type1();
LAB 15.3
346
Lab 15.3 Exercises