Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
50
Добавлен:
16.04.2013
Размер:
5.97 Mб
Скачать

Assigning Collections

BEGIN

FOR i IN names.FIRST .. names.LAST LOOP

IF names(i) = 'J Hamil' THEN NULL;

END IF; END LOOP;

END;

/

Example 5–17 Passing a Nested Table Element as a Parameter

This example shows that you can reference the elements of a collection in subprogram calls:

DECLARE

TYPE Roster IS TABLE OF VARCHAR2(15);

names Roster := Roster('J Hamil', 'D Piro', 'R Singh'); i BINARY_INTEGER := 2;

BEGIN

verify_name(names(i)); -- call procedure END;

/

Assigning Collections

One collection can be assigned to another by an INSERT, UPDATE, FETCH, or SELECT statement, an assignment statement, or a subprogram call.

You can assign the value of an expression to a specific element in a collection using the syntax:

collection_name(subscript) := expression;

where expression yields a value of the type specified for elements in the collection type definition.

You can use operators such as SET, MULTISET UNION, MULTISET INTERSECT, and

MULTISET EXCEPT to transform nested tables as part of an assignment statement.

Example 5–18 Datatype Compatibility for Collection Assignment

This example shows that collections must have the same datatype for an assignment to work. Having the same element type is not enough.

DECLARE

TYPE last_name_typ IS VARRAY(3) OF VARCHAR2(64);

TYPE surname_typ IS VARRAY(3) OF VARCHAR2(64);

--These first two variables have the same datatype.

group1 last_name_typ := last_name_typ('Jones','Wong','Marceau'); group2 last_name_typ := last_name_typ('Klein','Patsos','Singh');

--This third variable has a similar declaration, but is not the same type. group3 surname_typ := surname_typ('Trevisi','Macleod','Marquez');

BEGIN

--Allowed because they have the same datatype group1 := group2;

--Not allowed because they have different datatypes

--group3 := group2;

END;

Using PL/SQL Collections and Records 5-13

Assigning Collections

/

Example 5–19 Assigning a Null Value to a Nested Table

If you assign an atomically null nested table or varray to a second nested table or varray, the second collection must be reinitialized:

DECLARE

TYPE Colors IS TABLE OF VARCHAR2(64);

--This nested table has some values. crayons Colors := Colors('Silver','Gold');

--This nested table is not initialized ("atomically null").

empty_set Colors; BEGIN

--At first, the initialized variable is not null. if crayons IS NOT NULL THEN

dbms_output.put_line('OK, at first crayons is not null.'); END IF;

--Then we assign a null nested table to it. crayons := empty_set;

--Now it is null.

if crayons IS NULL THEN

dbms_output.put_line('OK, now crayons has become null.'); END IF;

--We must use another constructor to give it some values. crayons := Colors('Yellow','Green','Blue');

END;

/

In the same way, assigning the value NULL to a collection makes it atomically null.

Example 5–20 Possible Exceptions for Collection Assignments

Assigning a value to a collection element can cause various exceptions:

If the subscript is null or is not convertible to the right datatype, PL/SQL raises the predefined exception VALUE_ERROR. Usually, the subscript must be an integer. Associative arrays can also be declared to have VARCHAR2 subscripts.

If the subscript refers to an uninitialized element, PL/SQL raises SUBSCRIPT_ BEYOND_COUNT.

If the collection is atomically null, PL/SQL raises COLLECTION_IS_NULL.

DECLARE

TYPE WordList IS TABLE OF VARCHAR2(5); words WordList;

BEGIN

/* Assume execution continues despite the raised exceptions. */

--Raises COLLECTION_IS_NULL. We haven't used a constructor yet.

--This exception applies to varrays and nested tables, but not to

--associative arrays which don't need a constructor. words(1) := 10;

--After using a constructor, we can assign values to the elements. words := WordList(10,20,30);

--Any expression that returns a VARCHAR2(5) is OK. words(1) := 'yes';

words(2) := words(1) || 'no';

5-14 PL/SQL User's Guide and Reference

Assigning Collections

--Raises VALUE_ERROR because the assigned value is too long. words(3) := 'longer than 5 characters';

--Raises VALUE_ERROR because the subscript of a nested table must

--be an integer. words('B') := 'dunno';

--Raises SUBSCRIPT_BEYOND_COUNT because we only made 3 elements

--in the constructor. To add new ones, we must call the EXTEND

--method first. words(4) := 'maybe';

END;

/

Example 5–21 Assigning Nested Tables with Set Operators

This example shows some of the ANSI-standard operators that you can apply to nested tables:

DECLARE

TYPE nested_typ IS TABLE OF NUMBER; nt1 nested_typ := nested_typ(1,2,3); nt2 nested_typ := nested_typ(3,2,1); nt3 nested_typ := nested_typ(2,3,1,3); nt4 nested_typ := nested_typ(1,2,4); answer nested_typ;

--The results might be in a different order than you expect.

--(Remember, you should not rely on the order of elements in nested tables.) PROCEDURE print_nested_table(the_nt nested_typ) IS

output VARCHAR2(128); BEGIN

IF the_nt IS NULL THEN dbms_output.put_line('Results: <NULL>'); RETURN;

END IF;

IF the_nt.COUNT = 0 THEN dbms_output.put_line('Results: empty set'); RETURN;

END IF;

FOR i IN the_nt.FIRST .. the_nt.LAST LOOP

output := output || the_nt(i) || ' ';

END LOOP;

dbms_output.put_line('Results: ' || output); END;

BEGIN

answer := nt1 MULTISET UNION nt4; -- (1,2,3,1,2,4) print_nested_table(answer);

answer := nt1 MULTISET UNION nt3; -- (1,2,3,2,3,1,3) print_nested_table(answer);

answer := nt1 MULTISET UNION DISTINCT nt3; -- (1,2,3) print_nested_table(answer);

answer := nt2 MULTISET INTERSECT nt3; -- (3,2,1) print_nested_table(answer);

answer := nt2 MULTISET INTERSECT DISTINCT nt3; -- (3,2,1) print_nested_table(answer);

answer := SET(nt3); -- (2,3,1) print_nested_table(answer);

Using PL/SQL Collections and Records 5-15

Comparing Collections

answer := nt3 MULTISET EXCEPT nt2; -- (3) print_nested_table(answer);

answer := nt3 MULTISET EXCEPT DISTINCT nt2; -- () print_nested_table(answer);

END;

/

Comparing Collections

You can check whether a collection is null, and whether two collections are the same. Comparisons such as greater than, less than, and so on are not allowed.

This restriction also applies to implicit comparisons. For example, collections cannot appear in a DISTINCT, GROUP BY, or ORDER BY list.

If you want to do such comparison operations, you must define your own notion of what it means for collections to be greater than, less than, and so on, and write one or more functions to examine the collections and their elements and return a true or false value.

You can apply set operators (CARDINALITY, MEMBER OF, IS A SET, IS EMPTY) to check certain conditions within a nested table or between two nested tables.

Example 5–22 Checking if a Collection Is Null

Nested tables and varrays can be atomically null, so they can be tested for nullity:

DECLARE

TYPE Staff IS TABLE OF Employee; members Staff;

BEGIN

-- Condition yields TRUE because we haven't used a constructor. IF members IS NULL THEN ...

END;

Example 5–23 Comparing Two Collections

Collections can be compared for equality or inequality. They cannot be ordered, because there is no "greater than" or "less than" comparison.

DECLARE

TYPE Colors IS TABLE OF VARCHAR2(64);

primaries Colors := Colors('Blue','Green','Red'); rgb Colors := Colors('Red','Green','Blue');

traffic_light Colors := Colors('Red','Green','Amber'); BEGIN

--We can use = or !=, but not < or >.

--Notice that these 2 are equal even though the members are in different order. IF primaries = rgb THEN

dbms_output.put_line('OK, PRIMARIES and RGB have the same members.'); END IF;

IF rgb != traffic_light THEN

dbms_output.put_line('OK, RGB and TRAFFIC_LIGHT have different members.'); END IF;

END;

/

5-16 PL/SQL User's Guide and Reference

Соседние файлы в папке Oracle 10g