Académique Documents
Professionnel Documents
Culture Documents
Why Collections?
Just about all modern programming languages provide support for collections. A collection can be
loosely defined as a group of ordered elements, all of the same type, that allows programmatic
access to its elements through an index. Commonly used collection types used in the
programming world include arrays, maps, and lists.
Storing elements in a collection can provide a number of advantages. For starters, collections can
help to simplify code. If you need to process a number of items of a similar type, storing these
items in a collection will allow you to loop through each element with ease, referencing each one
by an index. In addition, most languages define collection types that contain built-in methods to
operate on the collection. For example, a method might allow you to remove all elements from a
collection in a single command.
Probably the biggest advantage a collection can provide is improved application performance.
Developers utilize collections to 'cache' static data that needs to be regularly accessed. This
results in reduced calls to a database. As I stated earlier, PL/SQL programs are a good place to
make expensive SQL calls but that doesn't mean that we shouldn't try to keep those calls to a
minimum.
Oracle provides three types of PL/SQL collections: nested tables, varrays, and associative arrays.
We will review each of these collection types in turn. But first, let's take a quick look at traditional
approaches to collections programming. At its conclusion, this article will offer some suggestions
on when to use each of them.
Traditional Approaches
With the release of Oracle 7, Oracle introduced the PL/SQL Table. By using PL/SQL Tables, it
was possible to create a collection of items, all of the same type, indexed by an integer.
PL/SQL tables were often combined with PL/SQL Records. By creating a PL/SQL Record,
developers could define a composite type that allowed you to group items of varying type
together. Combining PL/SQL Tables and Records together was often referred to as a 'PL/SQL
Table of Records'.
my_book_rec book_rec%TYPE;
my_book_rec_tab book_rec_tab%TYPE;
...
...
my_book_rec := my_book_rec_tab(5);
find_authors_books(my_book_rec.author);
...
...
In version 8, Oracle introduced two collection types, Nested Tables and Varrays. At this time, the
PL/SQL Table was renamed to 'index-by table'. As of Oracle 9i, PL/SQL Tables (index-by tables)
have again been renamed to Associative Arrays. The Associative Array functions much the same
way the PL/SQL Table of old did. However, the Associative Array does contain some enhanced
functionality, as we will see.
Varrays
The Varray is short for Variable Array. A Varray stores elements of the same type in the order in
which they are added. The number of elements in a Varray must be known at the time of its
declaration. In other words, a Varray has a fixed lower and upper bounds, making it most similar
to collection types from other programming languages. Once it is created and populated, each
element can be accessed by a numeric index.
The following statements declare, and then populate, a Varray that will contain 4 elements of the
same type as the column genre_name in table book_genre:
DECLARE
TYPE genres IS VARRAY(4) OF book_genre.genre_name%TYPE;
Fiction_genres genres;
BEGIN
fiction_genres := genres('MYSTERY','SUSPENSE', 'ROMANCE','HORROR');
END;
We could have declared genres to be of type VARCHAR2(30) because all values here are text.
However, in keeping with good Oracle programming practices, you should always prefer to
declare variables that are based on table columns with the %TYPE attribute. This allows your
code to grow with the database schema. If we were to populate genres with a variable like
v_genre (versus a text literal), it would be easy for the column type to change in the database
without modifying our code.
All PL/SQL collections contain a number of built-in methods that prove useful when working with
them. Table 1 lists these Collection methods.
EXISTS Returns Boolean true if element at specified index exists; otherwise, false
TRIM Removes the last element, or the last n elements if a number is specified, ie.
TRIM(n)
**Cannot use with Associative Array
END IF;
...
...
--Remove all entries.
IF deleting_all_genres THEN
Fiction_genres.DELETE();
END IF;
The advantage that Varrays (and Nested Tables) have over Associative Arrays is their ability to
be added to the database. For example, you could add the genres type, a Varray, to a DML
statement on the library table.
NAME BOOK_GENRES
-------------------- ---------------------------------------------
Brand New Library GENRES('FICTION', 'NON-FICTION', 'HISTORY',
'BUSINESS AND FINANCE')
Note how the insertion order of elements in book_genres is retained. When a table contains a
Varray type, its data is included in-line, with the rest of the table's data. When a Varray datatype
is selected from a database table, all elements are retrieved. The Varray is ideal for storing fixed
values that will be processed collectively. It is not possible to perform inserts, updates, and
deletes on the individual elements in a Varray. If you require your collection to be stored in the
database but would like the flexibility to manipulate elements individually, Nested Tables are a
better solution.
Nested Table
Nested Tables, like the Varray, can be stored in a relational table as well as function as a PL/SQL
program variable. The syntax for declaring a Nested Table is similar to the syntax for declaring
the traditional PL/SQL Table. Let's rework our earlier example using a Nested Table. First, you
declare your type:
As stated earlier, a Varray's contents are stored in the same table as the other columns' data
(unless the collection is exceedingly large, then Oracle stores it in a BLOB, but still within the
same tablespace). With Nested Tables, a seperate database table will store the data. This table
is specified following the 'STORE AS' clause. If a database table has more than one Nested
Table type, the same storage table will store data for all the Nested Tables on that parent table.
These storage tables contain a column called NESTED_TABLE_ID that allows the parent table to
reference a row's nested table data.
END;
/
These examples show an insert and an update to the book_table and are similar to what you
might see if you were working with a Varray. Both Nested Tables and Varrays allow you to use
SQL to select individual elements from a collection. However, Nested Tables have an advantage
over Varrays in that they allow for inserts, updates, and deletes on individual elements. The
Varray type does not because Varray data is stored as one single, delimited piece of data within
the database.
To operate on collection elements, use the TABLE command. The TABLE command operator
informs Oracle that you want your operations to be directed at the collection, instead of its parent
table.
--1.)Select all genres from library 'Brand New Library' that are like
'%FICTION%'.
SELECT column_value FROM TABLE(SELECT book_genres_tab
FROM book_library
WHERE name = 'Brand New Library')
WHERE column_value LIKE '%FICTION%';
/
COLUMN_VALUE
------------------------------
FICTION
NON-FICTION
COLUMN_VALUE
------------------------------
FICTION
NON-FICTION
HISTORY
BUSINESS AND FINANCE
SCIENCE
PERIODICALS
MULTIMEDIA
The first of the preceding three statements simply selects an individual element from the Nested
Table, book_genres_tab, in our book_library database table. The second statement performs an
update on an individual element, something possible only with Nested Tables. The last query
shown selects all Nested Table elements from the parent table. This demonstrates an important
feature of the TABLE operator. An ealier query we performed on a database column of type
Varray returned a single comma-delimited list of values ('FICTION', 'NON-FICTION', 'HISTORY',
'BUSINESS AND FINANCE'). Using TABLE allows you to 'unnest' a collection and display its
elements as you would a database table's results, top down.
Associative Array
Earlier, we reviewed the definition of a PL/SQL Table (also know as an index-by table). The
statement
TITLE
------------------------------
A Farewell to Arms
For Whom the Bell Tolls
The Sun Also Rises
Above are values from the title column of the book table. If we needed to remove an entry, given
only the book title, we would have to search the entire collection in a somewhat inefficient
manner. The following is code illustrates this:
DECLARE
TYPE book_title_tab IS TABLE OF book.title%TYPE
INDEX BY book.title%TYPE;
book_titles book_title_tab;
BEGIN
book_titles.DELETE('A Farewell to Arms');
END;
By using an Associative Array of book.title%TYPE, we accomplish our mission in one line, without
the need to loop through the set. The main drawback to the Associative Array type is that, like the
PL/SQL Table type before it, you are not able to store them in the database. They are strictly for
internal use in PL/SQL applications. If this is all you require of a collection, the Associative Array's
indexing flexibility make it a good choice.
database
Varray
• Use when working with an unbounded list that needs to increase dynamically
• Use when you need to store in the database and operate on elements individually
Associative Array
• Use when there is no need to store the Collection in the database. Its speed and
indexing flexibility make it ideal for internal application use.
Conclusion
Oracle PL/SQL is not a difficult language to learn. However, like all good programming
languages, there are many things we can do to maximize efficiency and minimize complexity.
Given PL/SQL's power to interact with the database, it can be tempting to simply to fall into the
habit of making excessive database calls to do our work. Collections can help you build simpler,
faster Oracle database applications, the goal of every good PL/SQL developer.
If you are a member of the Oracle Technology Network, you can read the following chapter in the
PL/SQL User's Guide and Reference for additional information about PL/SQL Collections.