logo for asktheoracle.net
Home
AskTheOracle Blog
Oracle Tips & Tricks
Oracle Training
Oracle Tutorials
PL/SQL
SQL
Advanced Tutorials
Performance Tuning
Certification
Oracle 10g
Oracle 11g
Oracle and .Net
Oracle Utilities
Developer Tools
Oracle Questions?
Oracle News
Search This Site
About Us
Disclaimer
Privacy Policy
Contact Us
leftimage for asktheoracle.net

PLSQL Collections of Records 

PLSQL collections can be very useful for modeling more complex or sophisticated data types such as the array, table or set types that exist in other languages and Oracle PLSQL provides us with 3 types of collections:
  1. associative arrays (also known as index-by tables)
  2. VARRAYs (varying size arrays)
  3. nested tables

We can also have multi dimensional plsql collections.

But what do we if we need collections of complex data types rather than the simple data types of varchar2, char, or number?

Fortunately, PL/SQL alllows us to define our own complex data types by using the record structure and to creating PLSQL collections of them. This enables us to build
very sophisticated data structures as we'll see shortly.

Let's start with a straightforward example of creating and using a PL/SQL record and a collection of records.

Example 1: Defining and Using a PL/SQL record structure

DECLARE

  TYPE book_typ IS
RECORD
  (
    isbn         VARCHAR2(20)  
   ,title        VARCHAR2(2000)
   ,author       VARCHAR2(2000)
   ,publisher    VARCHAR2(120) 
   ,published_on DATE
  );
 
  TYPE books_tab IS TABLE OF book_typ;
 
  books    books_tab;
  a_book   book_typ;

BEGIN

 
a_book.title        :=
  'Oracle Database 10g Performance Tuning Tips and Techniques';
 
a_book.author       := 'Richard Niemiec';
 
a_book.publisher    := 'McGraw-Hill Osborne Media';
 
a_book.isbn         := '978-0072263053';
  a_book.published_on :=
                  to_date('30 July 2007','dd mon yyyy');

  books                 := books_tab(
a_book);
END;


In this example we define our type first (as always). In this case our type has multiple components so we declare a record structure (book_typ) to hold them. We can now use the record in our declarations for plsql collections. In this case the collection type (books_tab) is a nested table type of the just defined record type. This enables us to have multiple records which, as we'll see shortly, allows us to read and write plsql collections from and to our Oracle database in one operation.

Having defined our types we need to declare variables of those types to be able to use them. We define one variable books which is a plsql collection and another variable a_book which is able to hold one instance of the record type book_typ declared earlier.

Accessing the components in the plsql record is straight forward as each component has a name so it's just the variable name followed by the component name.

For example, the author field is accessed by the following statement:

  a_book.author       := 'Richard Niemiec';

Having populated our record we can then use this to initialise our nested table collection as each cell in the collection has the same structure as the record variable. To instantiate nested table type Oracle plsql collections we have to use the constructor routine which is the type name (see the tutorial on nested tables for more details). In this example we populate it with just 1 element (record). To add more we would use the extend method and then populate the new elements in a similar manner.

Oracle Tips & Tricks to SKYROCKET Your Career!

If you're not already a subscriber you're  missing out on a myriad of tips and techniques to help you become a better, faster, smarter developer. Subscribe now and ignite your career.

Example 2: Defining and Using a PL/SQL record structure in a multi-dimensional collection

DECLARE
 
  TYPE author_typ IS TABLE OF VARCHAR2(120);
 
  TYPE book_rec IS RECORD
  (
    isbn         VARCHAR2(20)
   ,title        VARCHAR2(2000)
   ,author       author_typ
   ,publisher    VARCHAR2(120)
   ,published_on DATE
  );
 
  TYPE book_tab IS TABLE OF book_rec;
 
  TYPE book_set_typ IS TABLE OF book_tab INDEX BY VARCHAR2(200);
 
  book     book_rec;

  book_set book_set_typ; --plsql multi-level collection variable
 
BEGIN

  book.title        :=
     'OCA: Oracle Database 11g Certfied Associate Study Guide';
  book.author       :=
      author_typ('Biju Thomas'
                ,'Robert G. Freeman'
                ,'Charles A. Pack'
                ,'Doug Sturns'
                );
  book.publisher    := 'Sybex';
  book.isbn         := '978-0470395141';
  book.published_on := TO_DATE('13 April 2009','dd mon yyyy');

  book_set('OCP Oracle 11g Certifcation Kit') :=
                     book_tab(book,book);
            -- intialise 1st book_set with 2 books (the same)

  book_set('OCP
Oracle 11g Certifcation Kit')(2).title :=
    'OCP: Oracle 11g Certfied Professional Study Guide';
            -- correct title of 2nd book in the set

  book_set('OCP 10g Certifcation Kit') := book_tab(book,book);
            -- intialise 2nd book_set with 2 books (the same)

  book_set('OCP 10g Certifcation Kit')(2).author(1) :=
                           'Tim Buterbaugh';

  book_set('OCP 10g Certifcation Kit')(1).author :=
             author_typ('Tim Buterbaugh'
                       ,'Chip Dawes'
                       ,'Bob Bryla'
                       ,'Doug Stuns'); 

  book_set('OCP 10g Certifcation Kit')(2).title :=
    'OCP: Oracle 10g Certfied Professional Study Guide';
                       -- change title of 2nd book in the set
END;


In this example, as always, we define our types first. As in the previous example, our type has multiple components so we declare a record structure (book_rec) to hold them. However this time each book can have multiple authors by vrtue of defining the author field as a nested table collection (author_type). We could also have used a VARRAY collection if we wished to limit the maximum number of authors a book can have.

The next declaration (books_tab) is again an example of nested table Oracle plsql collections. In this case it is a collection of the just defined record type (book_rec). This would allow us to store details of multiple books. However in this example we take it a step further by declaring an associative array type collection which enables to store sets (collections)  of books.

With the types (data structures) defined we can declare variables of those types so that we can use them. We define one variable book which holds one instance of the record type (book_rec) we declared earlier and the variable book_set to hold the details of our sets of books

The next step is to populate the fields (attributes) of the book (the PL/SQL record) and then use this to initialise our collection. The following statement

  book_set('OCP Oracle 11g Certifcation Kit') :=
                  book_tab(book,book);

creates one element in our top level associative array and creates and initialises two elements in the nested table plsql collection. This has the effect of creating one set of two books, although both books are initially the same. Next we change the title of the second book in our first set and creating a second set of books (initially both the same).

The next statement:

  book_set('OCP 10g Certifcation Kit')(2).author(1) :=
                           'Tim Buterbaugh';

changes the name of the first author of the 2nd book in our second set. Note that all the other author names remain unchanged.

The next statement uses the nested table constructor to re-initialise the (set of) authors' names of the first book in the second set.
  book_set('OCP 10g Certifcation Kit')(1).author :=
             author_typ('Tim Buterbaugh'
                       ,'Chip Dawes'
                       ,'Bob Bryla'
                       ,'Doug Stuns'); 


Finally we change the title of the second book in the second set of books.

  book_set('OCP 10g Certifcation Kit')(2).title :=
    'OCP: Oracle 10g Certfied Professional Study Guide';

Example 3: Reading/Writing PL/SQL collections From/To Oracle

In this example we define a record type the components of which are anchored to the definitions of columns in the database by use of %TYPE, plus a collection of records defined impilicitly and anchored to the definition of the employees table in our Oracle database by use of %ROWTYPE.
DECLARE

   TYPE dept_rec IS RECORD
   (
     dept_id   departments.department_id%TYPE
    ,dept_name departments.department_name%TYPE
   ); -- anchor definitions to reduce maintenance
   
   TYPE numtab IS TABLE OF employees%ROWTYPE;
    -- each element is same type as row in employees table
 
   dept dept_rec; -- single record variable
  
   emps numtab; -- nested table pl/sql collection

BEGIN

   /*
retrieve name and id of just 1 department */

   SELECT department_id,department_name
   INTO dept.dept_id, dept.dept_name
   FROM departments
   WHERE ROWNUM < 2;         
  
   /*
      use of bulk collect and forall with collections can
      significately improve performance of Oracle pl/sql code
   */

   SELECT * BULK COLLECT INTO emps FROM employees; 
   -- retrieve all employee details from Oracle in one hit
  
   FOR i IN emps.FIRST .. emps.LAST LOOP
      dbms_output.put_line(
         'emps('||i||').employee_id = '||emps(i).employee_id
                          );
   END LOOP;     

   FORALL J IN emps.FIRST .. emps.LAST
       INSERT INTO emp2 values emps(j);
           -- insert all employee details into emp2 in one hit

END;

The variable dept (which is a record type) is populated by reading columns of one row of the departments table and assigning them to the components of the record.

For PLSQL collections, Oracle provides the bulk collect option to populate the plsql collection using just one statement, however we can still access individual elements of our collection using the index.  Writing the collection to the database can be done either one element at a time (using a loop) or all in one go by use of the FORALL statment.

Looking for Oracle PL/SQL training courses? Learn PL/SQL from the experts and sky-rocket your career with Oracle PL/SQL training in the UK from Smartsoft.