Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 50 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
50
Dung lượng
257,57 KB
Nội dung
DID YOU KNOW?
What is the difference between a NULL collection and an empty collection? If a collection has not
been initialized, referencing its individual elements causes the following error:
DECLARE
TYPE integer_type IS TABLE OF INTEGER;
integer_tab integer_type;
v_counter integer := 1;
BEGIN
DBMS_OUTPUT.PUT_LINE (integer_tab(v_counter));
END;
DECLARE
*
ERROR at line 1:
ORA-06531: Reference to uninitialized collection
ORA-06512: at line 7
If a collection has been initialized so that it is empty, referencing its individual elements causes a
different error:
DECLARE
TYPE integer_type IS TABLE OF INTEGER;
integer_tab integer_type := integer_type();
v_counter integer := 1;
BEGIN
DBMS_OUTPUT.PUT_LINE (integer_tab(v_counter));
END;
DECLARE
*
ERROR at line 1:
ORA-06533: Subscript beyond count
ORA-06512: at line 7
COLLECTION METHODS
In the previous examples, you have seen one of the collection methods, EXTEND. A collection
method is a built-in function that is called using dot notation as follows:
collection_name
.
method_name
The following list explains collection methods that allow you to manipulate or gain information
about a particular collection:
.
EXISTS returns TRUE if a specified element exists in a collection. This method can be
used to avoid SUBSCRIPT_OUTSIDE_LIMIT exceptions.
.
COUNT returns the total number of elements in a collection.
LAB 15.1
322
PL/SQL Tables
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
.
EXTEND 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:
FOR EXAMPLE
DECLARE
TYPE index_by_type IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
index_by_table index_by_type;
TYPE nested_type IS TABLE OF NUMBER;
nested_table nested_type :=
nested_type(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
BEGIN
Populate index by table
FOR i IN 1 10 LOOP
index_by_table(i) := i;
END LOOP;
IF index_by_table.EXISTS(3) THEN
DBMS_OUTPUT.PUT_LINE ('index_by_table(3) =
'||index_by_table(3));
END IF;
delete 10th element from a collection
nested_table.DELETE(10);
delete elements 1 through 3 from a collection
nested_table.DELETE(1,3);
index_by_table.DELETE(10);
LAB 15.1
PL/SQL Tables
323
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
FOR EXAMPLE (continued)
DBMS_OUTPUT.PUT_LINE ('nested_table.COUNT =
'||nested_table.COUNT);
DBMS_OUTPUT.PUT_LINE ('index_by_table.COUNT = '||
index_by_table.COUNT);
DBMS_OUTPUT.PUT_LINE ('nested_table.FIRST =
'||nested_table.FIRST);
DBMS_OUTPUT.PUT_LINE ('nested_table.LAST = '||nested_table.LAST);
DBMS_OUTPUT.PUT_LINE ('index_by_table.FIRST = '||
index_by_table.FIRST);
DBMS_OUTPUT.PUT_LINE ('index_by_table.LAST =
'||index_by_table.LAST);
DBMS_OUTPUT.PUT_LINE ('nested_table.PRIOR(2) = '||
nested_table. PRIOR(2));
DBMS_OUTPUT.PUT_LINE ('nested_table.NEXT(2) = '||
nested_table.NEXT(2));
DBMS_OUTPUT.PUT_LINE ('index_by_table.PRIOR(2) = '||
index_by_table.PRIOR(2));
DBMS_OUTPUT.PUT_LINE ('index_by_table.NEXT(2) = '||
index_by_table.NEXT(2));
Trim last two elements
nested_table.TRIM(2);
Trim last element
nested_table.TRIM;
DBMS_OUTPUT.PUT_LINE('nested_table.LAST = '||nested_table.LAST);
END;
Consider the output returned by this example:
index_by_table(3) = 3
nested_table.COUNT = 6
index_by_table.COUNT = 9
nested_table.FIRST = 4
nested_table.LAST = 9
index_by_table.FIRST = 1
index_by_table.LAST = 9
nested_table.PRIOR(2) =
nested_table.NEXT(2) = 4
index_by_table.PRIOR(2) = 1
index_by_table.NEXT(2) = 3
nested_table.LAST = 7
PL/SQL procedure successfully completed.
LAB 15.1
324
PL/SQL Tables
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
The first line of the output
index_by_table(3) = 3
is produced because the EXISTS method returns TRUE. As a result, the IF statement
IF index_by_table.EXISTS(3) THEN
DBMS_OUTPUT.PUT_LINE ('index_by_table(3) = '||index_by_table(3));
END IF;
evaluates to TRUE as well.
The second and third lines of the output
nested_table.COUNT = 6
index_by_table.COUNT = 9
show the results of method COUNT after some elements were deleted from the associative array
and nested table.
Next, lines four through seven of the output
nested_table.FIRST = 4
nested_table.LAST = 9
index_by_table.FIRST = 1
index_by_table.LAST = 9
show the results of the FIRST and LAST methods. Notice that the FIRST method applied to the
nested table returns 4 because the first three elements were deleted earlier.
Next, lines eight through eleven of the output
nested_table.PRIOR(2) =
nested_table.NEXT(2) = 4
index_by_table.PRIOR(2) = 1
index_by_table.NEXT(2) = 3
show the results of the PRIOR and NEXT methods. Notice that the PRIOR method applied to
the nested table returns NULL because the first element was deleted earlier.
Finally, the last line of the output
nested_table.LAST = 7
shows the value of the last subscript after the last three elements were removed. As mentioned
earlier, as soon as the DELETE method is issued, PL/SQL keeps placeholders of the deleted
elements. Therefore, the first call of the TRIM method removes the ninth and tenth elements of
the nested table, and the second call of the TRIM method removes the eighth element of the
nested table. As a result, the LAST method returns value 7 as the last subscript of the nested
table.
LAB 15.1
PL/SQL Tables
325
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
▼
LAB 15.1 EXERCISES
This section provides exercises and suggested answers, with discussion related to how those answers
resulted. The most important thing to realize is whether your answer works.You should figure out the
implications 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 IS
SELECT description
FROM course;
TYPE course_type IS TABLE OF course.description%TYPE
INDEX BY BINARY_INTEGER;
course_tab course_type;
v_counter INTEGER := 0;
BEGIN
FOR course_rec IN course_cur LOOP
v_counter := v_counter + 1;
course_tab(v_counter) := course_rec.description;
END LOOP;
END;
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, the
actual associative array is declared as course_tab.
The executable section of the script populates the
course_tab table 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_counter is 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 IS
SELECT description
FROM course;
LAB 15.1
326
Lab 15.1 Exercises
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
TYPE course_type IS TABLE OF course.description%TYPE
INDEX BY BINARY_INTEGER;
course_tab course_type;
v_counter INTEGER := 0;
BEGIN
FOR course_rec IN course_cur LOOP
v_counter := v_counter + 1;
course_tab(v_counter):= course_rec.description;
DBMS_OUTPUT.PUT_LINE('course('||v_counter||'): '||
course_tab(v_counter));
END LOOP;
END;
Consider another version of the same script:
ch15_1c.sql, version 3.0
SET SERVEROUTPUT ON
DECLARE
CURSOR course_cur IS
SELECT description
FROM course;
TYPE course_type IS TABLE OF course.description%TYPE
INDEX BY BINARY_INTEGER;
course_tab course_type;
v_counter INTEGER := 0;
BEGIN
FOR course_rec IN course_cur LOOP
v_counter := v_counter + 1;
course_tab(v_counter):= course_rec.description;
END LOOP;
FOR i IN 1 v_counter LOOP
DBMS_OUTPUT.PUT_LINE('course('||i||'): '||course_tab(i));
END LOOP;
END;
When run, both versions produce the same output:
course(1): DP Overview
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
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
course(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
the screen.
ANSWER: The script should look similar to the following. Changes are shown in bold.
ch15_1d.sql, version 4.0
SET SERVEROUTPUT ON
DECLARE
CURSOR course_cur IS
SELECT description
FROM course;
TYPE course_type IS TABLE OF course.description%TYPE
INDEX BY BINARY_INTEGER;
course_tab course_type;
v_counter INTEGER := 0;
BEGIN
FOR course_rec IN course_cur LOOP
v_counter := v_counter + 1;
course_tab(v_counter) := course_rec.description;
END LOOP;
DBMS_OUTPUT.PUT_LINE('course('||course_tab.FIRST||'): '||
course_tab(course_tab.FIRST));
DBMS_OUTPUT.PUT_LINE('course('||course_tab.LAST||'): '||
course_tab(course_tab.LAST));
END;
Consider the statements
course_tab(course_tab.FIRST)
LAB 15.1
328
Lab 15.1 Exercises
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
and
course_tab(course_tab.LAST)
used in this example. Although these statements look somewhat different from the statements
you have seen so far, they produce the same effect as the
course_tab(1)
and
course_tab(30)
statements. As mentioned earlier, the FIRST and LAST methods return the subscripts of the first
and last elements of a collection, respectively. In this example, the associative array contains 30
elements, where the first element has a subscript of 1, and the last element has a subscript of 30.
This version of the script produces the following output:
course(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 on
the screen.
II) Delete the last element, and display the total number of elements of the associative array
again.
III) Delete the fifth element, and display the total number of elements and the subscript of the
last 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 IS
SELECT description
FROM course;
TYPE course_type IS TABLE OF course.description%TYPE
INDEX BY BINARY_INTEGER;
course_tab course_type;
v_counter INTEGER := 0;
BEGIN
FOR course_rec IN course_cur LOOP
v_counter := v_counter + 1;
course_tab(v_counter) := course_rec.description;
END LOOP;
Display the total number of elements in the associative array
DBMS_OUTPUT.PUT_LINE ('1. Total number of elements: '||
course_tab.COUNT);
LAB 15.1
Lab 15.1 Exercises
329
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Delete 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
course_tab.DELETE(5);
DBMS_OUTPUT.PUT_LINE ('3. Total number of elements: '||
course_tab.COUNT);
DBMS_OUTPUT.PUT_LINE ('3. The subscript of the last element: '||
course_tab.LAST);
END;
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 method
and 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 array
and 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, the
COUNT 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 deleted
from the middle of the associative array, the value returned by the LAST method is greater than
the 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
nested table.
ANSWER: The script should look similar to the following. Changes are shown in bold.
ch15_2a.sql, version 1.0
SET SERVEROUTPUT ON
DECLARE
CURSOR course_cur IS
SELECT description
FROM course;
LAB 15.1
330
Lab 15.1 Exercises
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
TYPE course_type IS TABLE OF course.description%TYPE;
course_tab course_type := course_type();
v_counter INTEGER := 0;
BEGIN
FOR course_rec IN course_cur LOOP
v_counter := v_counter + 1;
course_tab.EXTEND;
course_tab(v_counter) := course_rec.description;
END LOOP;
END;
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 the
script.
II) Trim the last element of the nested table, and then assign a new value to it. Execute the
script.
ANSWER:
I)
The script should look similar to the following. Changes are shown in bold.
ch15_2b.sql, version 2.0
SET SERVEROUTPUT ON
DECLARE
CURSOR course_cur IS
SELECT description
FROM course;
TYPE course_type IS TABLE OF course.description%TYPE;
course_tab course_type := course_type();
v_counter INTEGER := 0;
BEGIN
FOR course_rec IN course_cur LOOP
v_counter := v_counter + 1;
course_tab.EXTEND;
course_tab(v_counter) := course_rec.description;
END LOOP;
course_tab.DELETE(30);
course_tab(30) := 'New Course';
END;
II)
The script should look similar to the following. Changes are shown in bold.
ch15_2c.sql, version 3.0
SET SERVEROUTPUT ON
DECLARE
CURSOR course_cur IS
SELECT description
FROM course;
LAB 15.1
Lab 15.1 Exercises
331
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
[...]... LOOP extend the size of varray by 1 and copy the current element to the last element city_varray.EXTEND(1, i); END LOOP; Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Lab 15.2 Exercises LAB 15.2 341 In 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... 15.3.1 Use Multilevel Collections In this exercise, you learn more about multilevel collections Create the following PL/SQL script: ch15_4a.sql, version 1.0 SET SERVEROUTPUT ON DECLARE TYPE table_type1 IS TABLE OF INTEGER INDEX BY BINARY_INTEGER; TYPE table_type2 IS TABLE OF TABLE_TYPE1 INDEX BY BINARY_INTEGER; table_tab1 table_type1; table_tab2 table_type2; BEGIN FOR i IN 1 2 LOOP FOR j IN 1 3 LOOP IF... Date: 17-FEB-03 Name: Yvonne Winnicki Registration Date: 17-FEB-03 Name: Mike Madej Registration Date: 17-FEB-03 PL/SQL procedure successfully completed Note that because a cursor-based record is defined based on the rows returned by a cursor’s select statement, its declaration must be preceded by a cursor declaration In other words, a cursor-based record is dependent on a particular cursor and cannot... incomplete or malformed ORA-06550: line 2, column 16: PL/SQL: Item ignored ORA-06550: line 12, column 30: PLS-00320: the declaration of the type incomplete or malformed ORA-06550: line 12, column 7: PL/SQL: SQL Statement ignored ORA-06550: line 16, column 10: PLS-00320: the declaration of the type incomplete or malformed ORA-06550: line 15, column 7: PL/SQL: Statement ignored ORA-06550: line 17, column... Haven PL/SQL procedure successfully completed Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark LAB 15.3 342 LAB 15.3 Multilevel Collections LAB OBJECTIVE 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. .. variations 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: FOR EXAMPLE... DBMS_OUTPUT.PUT_LINE('varray.LAST = '||varray.LAST); END; Consider the output returned by this example: varray.COUNT = 6 varray.LIMIT = 10 varray.FIRST = 1 varray.LAST = 6 varray.LAST = 8 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Varrays LAB 15.2 337 varray(8) = 4 varray.LAST = 6 PL/SQL procedure successfully completed The first two lines of output varray.COUNT = 6... using the DELETE method As mentioned earlier, when the DELETE method is used, PL/SQL keeps a placeholder of the deleted element Therefore, the statement 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 TRIM method In this case, PL/SQL does not keep a placeholder of the trimmed element, because the TRIM... or malformed ORA-06550: line 17, column 7: PL/SQL: Statement ignored of this expression is of this expression is of this expression is of this expression is USER-DEFINED RECORDS So far, you have seen how to create records based on a table or cursor However, you may need to create a record that is not based on any table or any one cursor For such situations, PL/SQL provides a user-defined record type... '||sample_rec.field1); DBMS_OUTPUT.PUT_LINE ('sample_rec.field2 = '||sample_rec.field2); END; The output is as follows: sample_rec.field1 = 10 sample_rec.field2 = ABC PL/SQL procedure successfully completed RECORD COMPATIBILITY You have seen that a record is defined by its name, structure, and type However, it is important to realize that two records may have the same structure yet be of a different type As a result, . methods:
FOR EXAMPLE
DECLARE
TYPE index _by_ type IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
index _by_ table index _by_ type;
TYPE nested_type IS TABLE OF NUMBER;
nested_table. Populate index by table
FOR i IN 1 10 LOOP
index _by_ table(i) := i;
END LOOP;
IF index _by_ table.EXISTS(3) THEN
DBMS_OUTPUT.PUT_LINE ('index _by_ table(3)