PK pUIoa,mimetypeapplication/epub+zipPKpUIOEBPS/adobjcol.htm Support for Collection Datatypes

3 Support for Collection Datatypes

This chapter provides basic information about working with varrays and nested table collection datatypes. It explains how to create and manage collection datatypes.

This chapter contains these topics:

Creating Collection Datatypes

Oracle supports the varray and nested table collection datatypes.

If you need to store only a fixed number of items, or to loop through the elements in order, or you will often want to retrieve and manipulate the entire collection as a value, then use a varray.

If you need to run efficient queries on a collection, handle arbitrary numbers of elements, or perform mass insert, update, or delete operations, then use a nested table. See "Design Considerations for Collections".

Creating an Instance of a VARRAY or Nested Table

You create an instance of a collection type in the same way that you create an instance of any other object type, namely, by calling the type's constructor method. The name of a type's constructor method is simply the name of the type. You specify the elements of the collection as a comma-delimited list of arguments to the method.

Calling a constructor method with an empty list creates an empty collection of that type. Note that an empty collection is an actual collection that happens to be empty; it is not the same as a null collection. See "Design Considerations for Nested Tables" for more information on using nested tables.

Constructor Methods for Collections

Example 3-1 shows how a literal invocation of the constructor method is used in a SQL statement to insert values into a nested table type people_typ.

Example 3-1 Using the Constructor Method to Insert Values into a Nested Table

CREATE TYPE people_typ AS TABLE OF person_typ;
/
CREATE TABLE people_tab (
    group_no NUMBER,
    people_column people_typ )
    NESTED TABLE people_column STORE AS people_column_nt;

INSERT INTO people_tab VALUES (
            100,
            people_typ( person_typ(1, 'John Smith', '1-800-555-1212'),
                        person_typ(2, 'Diane Smith', NULL)));

When you declare a table column to be of an object type or collection type, you can include a DEFAULT clause. This provides a value to use in cases where you do not explicitly specify a value for the column. The DEFAULT clause must contain a literal invocation of the constructor method for that object or collection.

Example 3-2 shows how to use literal invocations of constructor methods to specify defaults for person_typ and people_typ:

Example 3-2 Creating the department_persons Table Using the DEFAULT Clause

CREATE TABLE department_persons (
  dept_no    NUMBER PRIMARY KEY,
  dept_name  CHAR(20),
  dept_mgr   person_typ DEFAULT person_typ(10,'John Doe',NULL),
  dept_emps  people_typ DEFAULT people_typ() )
  NESTED TABLE dept_emps STORE AS dept_emps_tab;

INSERT INTO department_persons VALUES 
   ( 101, 'Physical Sciences', person_typ(65,'Vrinda Mills', '1-800-555-4412'),
           people_typ( person_typ(1, 'John Smith', '1-800-555-1212'), 
                        person_typ(2, 'Diane Smith', NULL) ) );
INSERT INTO department_persons VALUES 
  ( 104, 'Life Sciences', person_typ(70,'James Hall', '1-800-555-4621'), 
    people_typ() );

Note that the term people_typ() is a literal invocation of the constructor method for an empty people_typ table.

Varrays

A varray is an ordered set of data elements. All elements of a given varray are of the same datatype or a subtype of the declared one. Each element has an index, which is a number corresponding to the element's position in the array. The index number is used to access a specific element.

When you define a varray, you specify the maximum number of elements it can contain, although you can change this number later. The number of elements in an array is the size of the array. Oracle allows arrays to be of variable size, which is why they are called varrays.

The following statement creates an array type email_list_arr that has no more than ten elements, each of datatype VARCHAR2(80).

CREATE TYPE email_list_arr AS VARRAY(10) OF VARCHAR2(80);
/

In Example 3-3, a VARRAY type is created that is an array of an object type. The phone_varray_typ VARRAY type is used as a datatype for a column in the dept_phone_list table. The INSERT statements show how to insert values into phone_varray_typ in the table.

Example 3-3 Creating and Populating a VARRAY Datatype

CREATE TYPE phone_typ AS OBJECT (
    country_code   VARCHAR2(2), 
    area_code      VARCHAR2(3),
    ph_number      VARCHAR2(7));
/
CREATE TYPE phone_varray_typ AS VARRAY(5) OF phone_typ;
/
CREATE TABLE dept_phone_list (
  dept_no NUMBER(5), 
  phone_list phone_varray_typ);

INSERT INTO dept_phone_list VALUES (
   100,
   phone_varray_typ( phone_typ ('01', '650', '5061111'),
                      phone_typ ('01', '650', '5062222'),
                      phone_typ ('01', '650', '5062525')));

Creating an array type, as with a SQL object type, does not allocate space. It defines a datatype, which you can use as:

  • The datatype of a column of a relational table.

  • An object type attribute.

  • The type of a PL/SQL variable, parameter, or function return value.

A varray is normally stored in line, that is, in the same tablespace as the other data in its row. If it is sufficiently large, Oracle stores it as a BLOB. See "Storage Considerations for Varrays".

You can create a VARRAY type of XMLType or of a LOB type for procedural purposes, such as in PL/SQL or in view queries. However, database storage of a varray of those types is not supported. This means that you cannot create an object table or an object type column of a varray type of XMLType or of a LOB type.


See Also:

Oracle Database SQL Reference for information and examples on the STORE AS LOB clause of the CREATE TABLE statement

Nested Tables

A nested table is an unordered set of data elements, all of the same datatype. No maximum is specified in the definition of the table and the order of the elements is not preserved. You select, insert, delete, and update in a nested table just as you do with ordinary tables using the TABLE expression.

Elements of a nested table are actually stored in a separate storage table that contains a column that identifies the parent table row or object to which each element belongs. A nested table has a single column, and the type of that column is a built-in type or an object type. If the column in a nested table is an object type, the table can also be viewed as a multi-column table, with a column for each attribute of the object type.

In Example 3-4, the table type used for the nested tables is declared with the CREATE TYPE ... IS TABLE OF statement. A table type definition does not allocate space. It defines a type, which you can use as:

  • The datatype of a column of a relational table

  • An object type attribute

  • A PL/SQL variable, parameter, or function return type

When a column in a relational table is of nested table type, Oracle stores the nested table data for all rows of the relational table in the same storage table. Similarly, with an object table of a type that has a nested table attribute, Oracle stores nested table data for all object instances in a single storage table associated with the object table. See Figure 8-2, "Nested Table Storage".

In Example 3-4, the NESTED TABLE clause specifies the storage name for the nested table. The storage name is used when creating an index on a nested table. The example uses person_typ defined in Example 2-1 and people_typ defined in Example 3-1.

Example 3-4 Creating and Populating Simple Nested Tables

CREATE TABLE students (
   graduation DATE, 
   math_majors people_typ, 
   chem_majors people_typ, 
   physics_majors people_typ)
  NESTED TABLE math_majors STORE AS math_majors_nt
  NESTED TABLE chem_majors STORE AS chem_majors_nt
  NESTED TABLE physics_majors STORE AS physics_majors_nt;

CREATE INDEX math_idno_idx ON math_majors_nt(idno);
CREATE INDEX chem_idno_idx ON chem_majors_nt(idno);
CREATE INDEX physics_idno_idx ON physics_majors_nt(idno);

INSERT INTO students (graduation) VALUES ('01-JUN-03');
UPDATE students
  SET math_majors = 
        people_typ (person_typ(12, 'Bob Jones', '111-555-1212'), 
                    person_typ(31, 'Sarah Chen', '111-555-2212'),
                    person_typ(45, 'Chris Woods', '111-555-1213')),
      chem_majors = 
        people_typ (person_typ(51, 'Joe Lane', '111-555-1312'), 
                    person_typ(31, 'Sarah Chen', '111-555-2212'),
                    person_typ(52, 'Kim Patel', '111-555-1232')),
   physics_majors = 
        people_typ (person_typ(12, 'Bob Jones', '111-555-1212'), 
                    person_typ(45, 'Chris Woods', '111-555-1213'))
WHERE graduation = '01-JUN-03';

A convenient way to access the elements of a nested table individually is to use a nested cursor or the TABLE function. See "Querying Collections".

Specifying a Tablespace When Storing a Nested Table

A nested table can be stored in a different tablespace than its parent table. In Example 3-5, the nested table is stored in the system tablespace:

Example 3-5 Specifying a Different Tablespace for Storing a Nested Table

CREATE TABLE people_tab (
    people_column people_typ )
    NESTED TABLE people_column STORE AS people_column_nt (TABLESPACE system);

If the TABLESPACE clause is not specified, then the storage table of the nested table is created in the tablespace where the parent table is created. For multilevel nested tables, Oracle creates the child table in the same tablespace as its immediate preceding parent table.

The user can issue ALTER TABLE MOVE statement to move a table to a different tablespace. If the user issues ALTER TABLE MOVE statement on a table with nested table columns, it only moves parent table, no action is taken on the nested table's storage tables. If the user wants to move a nested table s storage table to a different tablespace, issue ALTER TABLE MOVE on the storage table. For example:

ALTER TABLE people_tab MOVE TABLESPACE system;
ALTER TABLE people_column_nt MOVE TABLESPACE example;

Now the people_tab table is in system tablespace and nested table is stored in the example tablespace.

Varray Storage

Multilevel varrays are stored in one of two ways, depending on whether the varray is a varray of varrays or a varray of nested tables.

  • In a varray of varrays, the entire varray is stored inline in the row unless it is larger than approximately 4000 bytes or LOB storage is explicitly specified.

  • In a varray of nested tables, the entire varray is stored in a LOB, with only the LOB locator stored in the row. There is no storage table associated with nested table elements of a varray. The entire nested table collection is stored inside the varray.

You can explicitly specify LOB storage for varrays. The following example does this for the varray elements of a nested table. As Example 3-6 also shows, you can use the COLUMN_VALUE keyword with varrays as well as nested tables.

Example 3-6 Specifying LOB Storage for a VARRAY Elements of a Nested Table

CREATE TYPE email_list_arr AS VARRAY(10) OF VARCHAR2(80);
/

CREATE TYPE email_list_typ AS TABLE OF email_list_arr;
/

CREATE TABLE dept_email_list (
  dept_no NUMBER, 
  email_addrs email_list_typ)
  NESTED TABLE email_addrs STORE AS email_addrs_nt
  (VARRAY COLUMN_VALUE STORE AS LOB dept_emails_lob);

Example 3-7 shows explicit LOB storage specified for a varray of varray type.

Example 3-7 Specifying LOB Storage for a VARRAY Type

CREATE TYPE email_list_typ2 AS OBJECT (
    section_no   NUMBER, 
    emails       email_list_arr);
/

CREATE TYPE email_varray_typ AS VARRAY(5) OF email_list_typ2;
/

CREATE TABLE dept_email_list2 (
  dept_no NUMBER, 
  email_addrs email_varray_typ)
  VARRAY email_addrs STORE AS LOB dept_emails_lob2;

See "Storage Considerations for Varrays". See also Oracle Database Application Developer's Guide - Large Objects.

Increasing the Size and Precision of VARRAYs and Nested Tables

When the element type of a VARRAY type is a variable character or RAW type or a numeric type, you can increase the size of the variable character or RAW type or increase the precision of the numeric type. A new type version is generated for the VARRAY type. The same changes can be applied to nested table types.

Options like INVALIDATE and CASCADE are provided to either invalidate all dependent objects or propagate the change to its type and table dependents.

Example 3-8 is illustrates the use ALTER TYPE to increase the size of a VARRAY and a nested table element type.

Example 3-8 Increasing the Size of an Element Type in a VARRAY and Nested Table

CREATE TYPE email_list_arr AS VARRAY(10) OF VARCHAR2(80);
/
ALTER TYPE email_list_arr MODIFY ELEMENT TYPE VARCHAR2(100) CASCADE;

CREATE TYPE email_list_tab AS TABLE OF VARCHAR2(30);
/
ALTER TYPE email_list_tab MODIFY ELEMENT TYPE VARCHAR2(40) CASCADE;

Increasing VARRAY Limit Size

The ALTER TYPE ... MODIFY LIMIT syntax allows increasing the number of elements of a VARRAY type. If the number of elements of the VARRAY type is increased, a new type version is generated for the VARRAY type and this is maintained as part of the history of the type changes.

Options like INVALIDATE and CASCADE are provided to either invalidate all dependent objects or propagate the change to its type and table dependents.

Example 3-9 Increasing the VARRAY Limit Size

CREATE TYPE email_list_arr AS VARRAY(10) OF VARCHAR2(80);
/
CREATE TYPE email_list_typ AS OBJECT (
    section_no   NUMBER, 
    emails       email_list_arr);
/

CREATE TYPE email_varray_typ AS VARRAY(5) OF email_list_typ;
/

ALTER TYPE email_varray_typ MODIFY LIMIT 100 INVALIDATE;

When a VARRAY type is altered, changes are propagated to the dependent tables. See "Propagating VARRAY Size Change".

Creating a Varray Containing LOB References

In Example 3-10, email_addrs of type email_list_typ already exists in table dept_email_list as shown in the SQL examples in "Varray Storage".

To create a varray of LOB references, first define a VARRAY type of type REF email_list_typ2. Next define a column of the array type in dept_email_list3.

Example 3-10 Creating a VARRY Containing LOB References

CREATE TYPE ref_email_varray_typ AS VARRAY(5) OF REF email_list_typ;
/

CREATE TABLE dept_email_list3 (
  dept_no NUMBER, 
  email_addrs ref_email_varray_typ)
  VARRAY email_addrs STORE AS LOB dept_emails_lob3;

Multilevel Collection Types

Multilevel collection types are collection types whose elements are themselves directly or indirectly another collection type. Possible multilevel collection types are:

  • Nested table of nested table type

  • Nested table of varray type

  • Varray of nested table type

  • Varray of varray type

  • Nested table or varray of a user-defined type that has an attribute that is a nested table or varray type

Like ordinary, single-level collection types, multilevel collection types can be used as columns in a relational table or with object attributes in an object table.

Nested Table Storage Tables for Multilevel Collection Types

A nested table type column or object table attribute requires a storage table where rows for all nested tables in the column are stored. With a multilevel nested table collection of nested tables, the inner set of nested tables also requires a storage table just as the outer set does. You specify one by appending a second nested-table storage clause.

Example 3-11 creates a multilevel collection type that is a nested table of nested tables. The example models a system of corporate regions in which each region has a nested table collection of the countries, and each country has a nested table collection of its locations. This example is based on the regions, countries, and locations tables of the Oracle HR sample schema.

In Example 3-11, the SQL statements create a table region_tab that contains a column countries whose type is a multilevel collection. This multilevel collection is a nested table of an object type that has a nested table attribute locations. Separate nested table clauses are provided for the outer countries nested table and for the inner locations one.

Example 3-11 Multilevel Nested Table Storage

CREATE TYPE location_typ AS OBJECT (
  location_id      NUMBER(4),
  street_address   VARCHAR2(40),
  postal_code      VARCHAR2(12),
  city             VARCHAR2(30),
  state_province   VARCHAR2(25));
/

CREATE TYPE nt_location_typ AS TABLE OF location_typ;
/

CREATE TYPE country_typ AS OBJECT (
  country_id     CHAR(2),
  country_name   VARCHAR2(40),
  locations      nt_location_typ);
/

CREATE TYPE nt_country_typ AS TABLE OF country_typ;
/

CREATE TABLE region_tab (
  region_id     NUMBER,
  region_name   VARCHAR2(25),
  countries     nt_country_typ)
  NESTED TABLE countries STORE AS nt_countries_tab
   (NESTED TABLE locations STORE AS nt_locations_tab);

In Example 3-11 you can refer to the inner locations nested table by name because this nested table is a named attribute of an object. However, if the inner nested table is not an attribute, it has no name. The keyword COLUMN_VALUE is provided for this case; you use it in place of a name for an inner nested table as shown in Example 3-12.

Example 3-12 Multilevel Nested Table Storage Using the COLUMN_VALUE Keyword

CREATE TYPE inner_table AS TABLE OF NUMBER;
/
CREATE TYPE outer_table AS TABLE OF inner_table;
/
CREATE TABLE tab1 (
  col1 NUMBER,
  col2 outer_table)
NESTED TABLE col2 STORE AS col2_ntab
  (NESTED TABLE COLUMN_VALUE STORE AS cv_ntab);

Physical attributes for the storage tables can be specified in the nested table clause, as shown in Example 3-13.

Example 3-13 Specifying Physical Attributes for Nested Table Storage

CREATE TABLE region_tab (
  region_id     NUMBER,
  region_name   VARCHAR2(25),
  countries     nt_country_typ)
  NESTED TABLE countries STORE AS nt_countries_tab (
   (PRIMARY KEY (NESTED_TABLE_ID, country_id))
   ORGANIZATION INDEX COMPRESS
   NESTED TABLE locations STORE AS nt_locations_tab);

Every nested table storage table contains a column, referenceable by NESTED_TABLE_ID, that keys rows in the storage table to the associated row in the parent table. A parent table that is itself a nested table has two system-supplied ID columns: one, referenceable by NESTED_TABLE_ID, that keys its rows back to rows in its own parent table, and one hidden column referenced by the NESTED_TABLE_ID column in its nested table children.

In Example 3-13, nested table countries is made an index-organized table (IOT) by adding the ORGANIZATION INDEX clause and assigning the nested table a primary key in which the first column is NESTED_TABLE_ID. This column contains the ID of the row in the parent table with which a storage table row is associated. Specifying a primary key with NESTED_TABLE_ID as the first column and index-organizing the table cause Oracle to physically cluster all the nested table rows that belong to the same parent row, for more efficient access.

Each nested table needs its own table storage clause, so you must have as many nested table storage clauses as you have levels of nested tables in a collection. See "Nested Table Storage".

Assignment and Comparison of Multilevel Collections

As with single-level collections, both the source and the target must be of the same declared data type in assignments of multilevel collections.

Only items whose datatypes are nested table collection types, including multilevel collection types, can be compared. See "Comparisons of Collections".

Constructors for Multilevel Collections

Like single-level collection types, multilevel collection types are created by calling the respective type's constructor method. Like the constructor methods for other object types, a constructor for a multilevel collection type is a system-defined function that has the same name as the type and returns a new instance of it—in this case, a new multilevel collection. Constructor parameters have the names and types of the object type's attributes.

Example 3-14 shows the constructor call for the multilevel collection type nt_country_typ. This type is a nested table of countries, each of which contains a nested table of locations as an attribute. The constructor for the outer nested table calls the country_typ constructor for each country to be created; each country constructor calls the constructor for the locations nested table type to create its nested table of locations; and the locations nested table type constructor calls the location_typ constructor for each location instance to be created.

Example 3-14 Using Constructors for Multilevel Collections

INSERT INTO region_tab 
VALUES(1, 'Europe', nt_country_typ( 
  country_typ( 'IT', 'Italy', nt_location_typ (
    location_typ(1000, '1297 Via Cola di Rie','00989','Roma', ''),
    location_typ(1100, '93091 Calle della Testa','10934','Venice','') ) 
    ),
  country_typ( 'CH', 'Switzerland', nt_location_typ (
    location_typ(2900, '20 Rue des Corps-Saints', '1730', 'Geneva', 'Geneve'),
    location_typ(3000, 'Murtenstrasse 921', '3095', 'Bern', 'BE') ) 
    ),
  country_typ( 'UK', 'United Kingdom', nt_location_typ (
    location_typ(2400, '8204 Arthur St', '', 'London', 'London'),
    location_typ(2500, 'Magdalen Centre, The Oxford Science Park', 'OX9 9ZB',
                 'Oxford', 'Oxford'),
    location_typ(2600, '9702 Chester Road', '09629850293', 'Stretford',
                 'Manchester') )
      ) 
  )
);

Operations on Collection Datatypes

This section describes the operations on collection datatypes.

Querying Collections

There are two general ways to query a table that contains a column or attribute of a collection type. One way returns the collections nested in the result rows that contain them. The other way distributes or unnests collections such that each collection element appears on a row by itself.

Nesting Results of Collection Queries

The following queries use the department_persons table shown in Example 3-2. The column dept_emps is a nested table collection of person_typ type. The dept_emps collection column appears in the SELECT list like an ordinary, scalar column. Querying a collection column in the SELECT list like this nests the elements of the collection in the result row with which the collection is associated.

In Example 3-15 the query retrieves the nested collection of employees.

Example 3-15 Nesting Results of Collection Queries

SELECT d.dept_emps 
  FROM department_persons d;


DEPT_EMPS(IDNO, NAME, PHONE)
-------------------------------------------------------------
PEOPLE_TYP(PERSON_TYP(1, 'John Smith', '1-800-555-1212'),
PERSON_TYP(2, 'Diane Smith', '1-800-555-1243'))

The results are also nested if an object-type column in the SELECT list contains a collection attribute, even if that collection is not explicitly listed in the SELECT list itself. For example, the query SELECT * FROM department_persons would produce a nested result.

Unnesting Results of Collection Queries

Not all tools or applications are able to deal with results in a nested format. To view Oracle collection data using tools that require a conventional format, you must unnest, or flatten, the collection attribute of a row into one or more relational rows. You can do this by using a TABLE expression with the collection. A TABLE expression enables you to query a collection in the FROM clause like a table. In effect, you join the nested table with the row that contains the nested table.

The TABLE expression can be used to query any collection value expression, including transient values such as variables and parameters.

As in Example 3-15, the query in Example 3-16 retrieves the collection of employees, but the collection is unnested.

Example 3-16 Unnesting Results of Collection Queries

SELECT e.* 
  FROM department_persons d, TABLE(d.dept_emps) e;


IDNO NAME PHONE
---------- ------------------------------ ---------------
1 John Smith 1-800-555-1212
2 Diane Smith 1-800-555-1243

As shown in Example 3-16, a TABLE expression can have its own table alias. In the example, a table alias for the TABLE expression appears in the SELECT list to select columns returned by the TABLE expression.

The TABLE expression uses another table alias to specify the table that contains the collection column that the TABLE expression references. The expression TABLE(d.dept_emps) specifies the department_persons table as containing the dept_emps collection column. A TABLE expression can use the table alias of any table appearing to the left of it in a FROM clause to reference a column of that table. This way of referencing collection columns is called left correlation.

In the example, the department_persons table is listed in the FROM clause solely to provide a table alias for the TABLE expression to use. No columns from the department_persons table other than the column referenced by the TABLE expression appear in the result

The following example produces rows only for departments that have employees.

SELECT d.dept_no, e.* 
  FROM department_persons d, TABLE(d.dept_emps) e;

To get rows for departments that have no employees, you can use outer-join syntax:

SELECT d.dept_no, e.* 
  FROM department_persons d, TABLE(d.dept_emps) (+) e;

The (+) indicates that the dependent join between department_persons and e.dept_emps should be NULL-augmented. That is, there will be rows of department_persons in the output for which e.dept_emps is NULL or empty, with NULL values for columns corresponding to e.dept_emps.

Unnesting Queries Containing Table Expression Subqueries

The examples in "Unnesting Results of Collection Queries" show a TABLE expression that contains the name of a collection. Alternatively, a TABLE expression can contain a subquery of a collection.

Example 3-17 returns the collection of employees whose department number is 101.

Example 3-17 Using a Table Expression Containing a Subquery of a Collection

SELECT *
  FROM TABLE(SELECT d.dept_emps 
               FROM department_persons d
               WHERE d.dept_no = 101);

There are these restrictions on using a subquery in a TABLE expression:

  • The subquery must return a collection type

  • The SELECT list of the subquery must contain exactly one item

  • The subquery must return only a single collection; it cannot return collections for multiple rows. For example, the subquery SELECT dept_emps FROM department_persons succeeds in a TABLE expression only if table department_persons contains just a single row. If the table contains more than one row, the subquery produces an error.

Example 3-18 shows a TABLE expression used in the FROM clause of a SELECT embedded in a CURSOR expression.

Example 3-18 Using a Table Expression in a CURSOR Expression

SELECT d.dept_no, CURSOR(SELECT * FROM TABLE(d.dept_emps)) 
  FROM department_persons d
   WHERE d.dept_no = 101;

Unnesting Queries with Multilevel Collections

Unnesting queries can be used with multilevel collections, too, for both varrays and nested tables. Example 3-19 shows an unnesting query on a multilevel nested table collection of nested tables. From a table region_tab in which each region has a nested table of countries and each country has a nested table of locations, the query returns the names of all regions, countries, and locations.

Example 3-19 Unnesting Queries with Multilevel Collections Using the TABLE Function

SELECT r.region_name, c.country_name, l.location_id 
  FROM region_tab r, TABLE(r.countries) c, TABLE(c.locations) l;
 
-- the following query is optimized to run against the locations table
SELECT l.location_id, l.city 
  FROM region_tab r, TABLE(r.countries) c, TABLE(c.locations) l;

Because no columns of the base table region_tab appear in the second SELECT list, the query is optimized to run directly against the locations storage table.

Outer-join syntax can also be used with queries of multilevel collections. See "Viewing Object Data in Relational Form with Unnesting Queries".

Performing DML Operations on Collections

Oracle supports the following DML operations on nested table columns:

  • Inserts and updates that provide a new value for the entire collection

  • Piecewise Updates

    • Inserting new elements into the collection

    • Deleting elements from the collection

    • Updating elements of the collection.

Oracle does not support piecewise updates on VARRAY columns. However, VARRAY columns can be inserted into or updated as an atomic unit.

For piecewise updates of nested table columns, the DML statement identifies the nested table value to be operated on by using the TABLE expression.

The DML statements in Example 3-20 demonstrate piecewise operations on nested table columns.

Example 3-20 Piecewise Operations on Collections

INSERT INTO TABLE(SELECT d.dept_emps 
                  FROM department_persons d
                  WHERE d.dept_no = 101)
   VALUES (5, 'Kevin Taylor', '1-800-555-6212');

UPDATE TABLE(SELECT d.dept_emps 
                  FROM department_persons d
                  WHERE d.dept_no = 101) e   
   SET VALUE(e) = person_typ(5, 'Kevin Taylor', '1-800-555-6233')
   WHERE e.idno = 5;
     
DELETE FROM TABLE(SELECT d.dept_emps 
                  FROM department_persons d
                  WHERE d.dept_no = 101) e
   WHERE e.idno = 5;

Example 3-21 shows VALUE used to return object instance rows for updating:

Example 3-21 Using VALUE to Update a Nested Table

UPDATE TABLE(SELECT d.dept_emps FROM department_persons d 
               WHERE  d.dept_no = 101) p
   SET VALUE(p) = person_typ(2, 'Diane Smith', '1-800-555-1243')
   WHERE p.idno = 2;

Performing DML on Multilevel Collections

For multilevel nested table collections, DML can be done atomically, on the collection as a whole, or piecewise, on selected elements. For multilevel varray collections, DML operations can be done only atomically.

Collections as Atomic Data Items

The section "Constructors for Multilevel Collections" shows an example of inserting an entire multilevel collection with an INSERT statement. Multilevel collections can also be updated atomically with an UPDATE statement. For example, suppose v_country is a variable declared to be of the countries nested table type nt_country_typ. Example 3-22 updates region_tab by setting the countries collection as a unit to the value of v_country.

Example 3-22 Using UPDATE to Insert an Entire Multilevel Collection

INSERT INTO region_tab (region_id, region_name) VALUES(2, 'Americas');

DECLARE
  v_country nt_country_typ;
BEGIN
  v_country :=  nt_country_typ( country_typ( 
   'US', 'United States of America', nt_location_typ (
   location_typ( 1500,'2011 Interiors Blvd','99236','San Francisco','California'),
   location_typ(1600,'2007 Zagora St','50090','South Brunswick','New Jersey'))));
  UPDATE region_tab r 
    SET r.countries = v_country WHERE r.region_id = 2;
END;
/

Piecewise Operations on Nested Tables

Piecewise DML is possible only on nested tables, not on varrays.

Example 3-23 shows a piecewise insert operation on the countries nested table of nested tables. The example inserts a new country, complete with its own nested table of location_typ:

Example 3-23 Piecewise INSERT on a Multilevel Collection

INSERT INTO TABLE( SELECT countries FROM region_tab r WHERE r.region_id = 2) 
  VALUES ( 'CA', 'Canada', nt_location_typ( 
       location_typ(1800, '147 Spadina Ave', 'M5V 2L7', 'Toronto', 'Ontario')));

Example 3-24 performs a piecewise insert into an inner nested table to add a location for a country. Like the preceding, this example uses a TABLE expression containing a subquery that selects the inner nested table to specify the target for the insert.

Example 3-24 Piecewise INSERT into an Inner Nested Table

INSERT INTO TABLE( SELECT c.locations 
  FROM TABLE( SELECT r.countries FROM region_tab r WHERE r.region_id = 2) c
  WHERE c.country_id = 'US')
  VALUES (1700, '2004 Lakeview Rd', '98199', 'Seattle', 'Washington');
 
SELECT r.region_name, c.country_name, l.location_id 
  FROM region_tab r, TABLE(r.countries) c, TABLE(c.locations) l;

Comparisons of Collections

The conditions listed in this section allow comparisons of nested tables. There is no mechanism for comparing varrays. The SQL examples in this section use the nested tables created in Example 3-4.

Equal and Not Equal Comparisons

The equal (=) and not equal (<>) conditions determine whether the input nested tables are identical or not, returning the result as a Boolean value.

Two nested tables are equal if they have the same named type, have the same cardinality, and their elements are equal. Elements are equal depending on whether they are equal by the elements own equality definitions, except for object types which require a map method.

Example 3-25 Using an Equality Comparison with Nested Tables

SELECT p.name 
  FROM students, TABLE(physics_majors) p 
WHERE math_majors = physics_majors;

In Example 3-25, the nested tables contain person_typ objects which have an associated map method. See Example 2-1.

In Comparisons

The IN condition checks whether a nested table is in a list of nested tables, returning the result as a Boolean value. NULL is returned if the nested table is a null nested table.

Example 3-26 Using an IN Comparison with Nested Tables

SELECT p.idno, p.name 
  FROM students, TABLE(physics_majors) p 
WHERE physics_majors IN (math_majors, chem_majors);

Subset of Multiset Comparison

The SUBMULTISET [OF] condition checks whether a nested table is a subset of a another nested table, returning the result as a Boolean value. The OF keyword is optional and does not change the functionality of SUBMULTISET.

This operator is implemented only for nested tables because this is a multiset function only.

Example 3-27 Testing the SUBMULTISET OF Condition on a Nested Table

SELECT p.idno, p.name 
  FROM students, TABLE(physics_majors) p 
WHERE physics_majors SUBMULTISET OF math_majors;

Member of a Nested Table Comparison

The MEMBER [OF] or NOT MEMBER [OF] condition tests whether an element is a member of a nested table, returning the result as a Boolean value. The OF keyword is optional and has no effect on the output.

Example 3-28 Using MEMBER OF on a Nested Table

SELECT graduation 
  FROM students 
WHERE person_typ(12, 'Bob Jones', '1-800-555-1212') MEMBER OF math_majors;

In Example 3-28, person_typ (12, 'Bob Jones', '1-800-555-1212') is an element of the same type as the elements of the nested table math_majors.

Empty Comparison

The IS [NOT] EMPTY condition checks whether a given nested table is empty or not empty, regardless of whether any of the elements are NULL. If a NULL is given for the nested table, the result is NULL. The result is returned as a Boolean value.

Example 3-29 Using IS NOT on a Nested Table

SELECT p.idno, p.name 
  FROM students, TABLE(physics_majors) p 
WHERE physics_majors IS NOT EMPTY;

Set Comparison

The IS [NOT] A SET condition checks whether a given nested table is composed of unique elements, returning a Boolean value.

Example 3-30 Using IS A SET on a Nested Table

SELECT p.idno, p.name 
  FROM students, TABLE(physics_majors) p 
WHERE physics_majors IS A SET;

Multisets Operations

This section describes multiset operations with nested tables. For a description of additional operations, see "Comparisons of Objects, REF Variables, and Collections". The SQL examples in this section use the nested tables created in Example 3-4.

For more information about using operators with nested tables, see Oracle Database SQL Reference.

CARDINALITY

The CARDINALITY function returns the number of elements in a varray or nested table. The return type is NUMBER. If the varray or nested table is a null collection, NULL is returned.

Example 3-31 Determining the CARDINALITY of a Nested Table

SELECT CARDINALITY(math_majors) 
  FROM students;

For more information about the CARDINALITY function, see Oracle Database SQL Reference.

COLLECT

The COLLECT function is an aggregate function which would create a multiset from a set of elements. The function would take a column of the element type as input and create a multiset from rows selected. To get the results of this function you must use it within a CAST function to specify the output type of COLLECT. See "CAST" for an example of the COLLECT function.

For more information about the COLLECT function, see Oracle Database SQL Reference.

MULTISET EXCEPT

The MULTISET EXCEPT operator inputs two nested tables and returns a nested table whose elements are in the first nested table but not in the second nested table. The input nested tables and the output nested table are all type name equivalent.

The ALL or DISTINCT options can be used with the operator. The default is ALL.

  • With the ALL option, for ntab1 MULTISET EXCEPT ALL ntab2, all elements in ntab1 other than those in ntab2 would be part of the result. If a particular element occurs m times in ntab1 and n times in ntab2, the result will have (m - n) occurrences of the element if m is greater than n otherwise 0 occurrences of the element.

  • With the DISTINCT option, any element that is present in ntab1 which is also present in ntab2 would be eliminated, irrespective of the number of occurrences.

Example 3-32 Using the MULTISET EXCEPT Operation on Nested Tables

SELECT math_majors MULTISET EXCEPT physics_majors 
  FROM students 
WHERE graduation = '01-JUN-03';

For more information about the MULTISET EXCEPT operator, see Oracle Database SQL Reference.

MULTISET INTERSECTION

The MULTISET INTERSECT operator returns a nested table whose values are common in the two input nested tables. The input nested tables and the output nested table are all type name equivalent.

There are two options associated with the operator: ALL or DISTINCT. The default is ALL. With the ALL option, if a particular value occurs m times in ntab1 and n times in ntab2, the result would contain the element MIN(m, n) times. With the DISTINCT option the duplicates from the result would be eliminated, including duplicates of NULL values if they exist.

Example 3-33 Using the MULTISET INTERSECT Operation on Nested Tables

SELECT math_majors MULTISET INTERSECT physics_majors 
  FROM students 
WHERE graduation = '01-JUN-03';

For more information about the MULTISET INTERSECT operator, see Oracle Database SQL Reference.

MULTISET UNION

The MULTISET UNION operator returns a nested table whose values are those of the two input nested tables. The input nested tables and the output nested table are all type name equivalent.

There are two options associated with the operator: ALL or DISTINCT. The default is ALL. With the ALL option, all elements that are in ntab1 and ntab2 would be part of the result, including all copies of NULLs. If a particular element occurs m times in ntab1 and n times in ntab2, the result would contain the element (m + n) times. With the DISTINCT option the duplicates from the result are eliminated, including duplicates of NULL values if they exist.

Example 3-34 Using the MULTISET UNION Operation on Nested Tables

SELECT math_majors MULTISET UNION DISTINCT physics_majors 
  FROM students 
WHERE graduation = '01-JUN-03';



PEOPLE_TYP(PERSON_TYP(12, 'Bob Jones', '1-800-555-1212'),
       PERSON_TYP(31, 'Sarah Chen', '1-800-555-2212'),
       PERSON_TYP(45, 'Chris Woods', '1-800-555-1213'))
SELECT math_majors MULTISET UNION ALL physics_majors
  FROM students 
WHERE graduation = '01-JUN-03';


PEOPLE_TYP(PERSON_TYP(12, 'Bob Jones', '1-800-555-1212'),
    PERSON_TYP(31, 'Sarah Chen', '1-800-555-2212'),
    PERSON_TYP(45, 'Chris Woods', '1-800-555-1213'),
    PERSON_TYP(12, 'Bob Jones', '1-800-555-1212'),
    PERSON_TYP(45, 'Chris Woods', '1-800-555-1213'))

For more information about the MULTISET UNION operator, see Oracle Database SQL Reference.

POWERMULTISET

The POWERMULTISET function generates all non-empty submultisets from a given multiset. The input to the POWERMULTISET function could be any expression which evaluates to a multiset. The limit on the cardinality of the multiset argument is 32.

Example 3-35 Using the POWERMULTISET Operation on Multiset

SELECT * FROM TABLE(POWERMULTISET( people_typ (
           person_typ(12, 'Bob Jones', '1-800-555-1212'), 
           person_typ(31, 'Sarah Chen', '1-800-555-2212'), 
           person_typ(45, 'Chris Woods', '1-800-555-1213'))));

For more information about the POWERMULTISET function, see Oracle Database SQL Reference.

POWERMULTISET_BY_CARDINALITY

The POWERMULTISET_BY_CARDINALITY function returns all non-empty submultisets of a nested table of the specified cardinality. The output would be rows of nested tables.

POWERMULTISET_BY_CARDINALITY(x, l) is equivalent to TABLE(POWERMULTISET(x)) p where CARDINALITY(value(p)) = l, where x is a multiset and l is the specified cardinality.

The first input parameter to the POWERMULTISET_BY_CARDINALITY could be any expression which evaluates to a nested table. The length parameter should be a positive integer, otherwise an error will be returned. The limit on the cardinality of the nested table argument is 32.

Example 3-36 Using the POWERMULTISET_BY_CARDINALITY Function

SELECT * FROM TABLE(POWERMULTISET_BY_CARDINALITY( people_typ (
           person_typ(12, 'Bob Jones', '1-800-555-1212'), 
           person_typ(31, 'Sarah Chen', '1-800-555-2212'), 
           person_typ(45, 'Chris Woods', '1-800-555-1213')),2));

For more information about the POWERMULTISET_BY_CARDINALITY function, see Oracle Database SQL Reference.

SET

The SET function converts a nested table into a set by eliminating duplicates, and returns a nested table whose elements are DISTINCT from one another. The nested table returned is of the same named type as the input nested table.

Example 3-37 Using the SET Function on a Nested Table

SELECT SET(physics_majors) 
  FROM students 
WHERE graduation = '01-JUN-03';

For more information about the SET function, see Oracle Database SQL Reference.

PKF PKpUIOEBPS/adobj016.gifx7GIF89a' ߟ___///oooOOO@@@𠠠000 ppp```PPP???! ,'@pHB<Ȥrl:ШtJZجvzx|hn|N~yhCgHEѻİDߛB#[ t`bŇ 5@(c ~shR"% D* NaI$ `Â$2Rj` ˑ,J f.+T&a) 8FzU*Hz]$4ERH $AIHHP4,9D@6ʔtNJO]P ^M8蕀ӧ7&M(k[HL-4S.`#}yǕ&XX}?|h=>LL?5wM%YURetiuiMp}ДJ@u@yhBUq@D'1pLu"ID$ $u^$:Eɏa H5awVFbvX3 d%69:~0}H`~UYSUji[xSzT)5g$CUVPyII!c&J@UQv&b7$6b",cFeaASj}!ԪCd{1 q盳ԐP5׍(@SV}P@ӭ$Ug~l\'I 3uPџ-s]i&[$׆r)#"c X_5-P t`h]ZskL0fVj`WPKbFQ5[KCe$C[o.W^H޿e5+_*֟ +8)0%A͠rT !/ʫNĤ,18R nYd f0<Y$pEq:Jc&75h,^D(af$`Ai l(n1SohH' <@0Vb\3%;8 Vjvjtm:: KR3鈘@ jFю HMj/x:PS9ӨZXY5`ծzS5WJVeMZ=sֵ'l+\J׀ȵx<׾5y/-#.g |PNpbFU.AS[!Ri %Ng$4E-am Bi6;p -ŭJBۗ + p"BZC- +H h(Z'Z+0xUNb&]b0Z9NrCݳy4K-)hE7p9paE^$4aɢT/u,% K_bl,sr=29mY!G))w8H^F"Bȋh; GOsrey*尅kIsYnn űFu Y;e1Cj+A:rɭQv2ZAOНRc Vo0@9aiq_ JЈVxXg; lHa3N&a O**&]aH: s"W{DÅ5XM&ҥ#yp;>xq8 @)ihUSL^T^H4t |#uN} wF{EP %=A8 ˃vӀ:gYPrY\Cf)zQ*sm'I>zZ/;>Hwhm_7NC,uv^wEQDw}&4t;X$9J-7~).+c?;S#>`n@b!f҂]j#یָ.? [eXGVލc5UeEOa@ pR̃E!,WRmb-ۑ1fbYlPBY!\1!+du&[%]=%q'edGy%Buv`u`w @hEX ]bGxBO8Q8VLO>HS0Y[UU چQ]eU_BW(cNgxohUiQN؆߀P5XhPlWrdp؈U|RuTz ToT ThXkx( (T~1@\(ac:dwzo3"o@ U &:A^( Q%#H͓`fOU9ZlK%OP8b8oG'.wBQ*钢dEVc@&=9{$ZA/`rmsTNp"l+JɔJYcD=2Zi @ bQ_M c9A+*Մ_DYuu&kkD%XvO7?*Օ ?c&?,=)PdƢr#J` {H/f<ȅ|яQc\-ca<0w; g "PAm cB[W œڇ&s@ζc ~S-y@1Y J Q x_5.*&. 97I#Z[ 8P'IeJpXgb#M @r 2:T6MqvPw)kZgI.W:vA^eQ3" %B{r` h_ Rttt*SAb IBΩps7 /4Ai mo-`bjuS Pj41)ZPfBoXa(~ᕏ!tS UQMBWХa6]a`vxyʦcxxJ$l9w>*f=ID ~41D2 *4DtB1j0Jq:Bl)e Q.uPPj QhC"Oa&Y9د۰ ;԰ 0ہ#1.8(kK#ѳOG<l~h[ȌuM״ꀵIⱾ s%BUg|Gr+[apb]Sڥ5b%ddej0uC9-jq_zszgr$g&D|sf=5b;r#{7[{;&z$g=(w8fV'8)!LQR n"uF[ cr7A:$RV &)kޕeqWKJ'!7`aw^xŻ+r"Jyq~^Vxd_PM "C3f bfRuCI0:*Ȝs'S|&2tL5C`qYu4ȣeaQquk+FdhkҦjj'|kؠhp}£ЉNV7 s1s#=+~ &G~I D"7=cA;m JI!:_A#X!-(:u;| FՁomI2iLG.l%og!KɂQ*}/RLnrTugMS<jot?LQ,H9 Ǐ:kٽ* V{BÆ)!ĨǮ#%d%| E#ْKKlyGdVYЃEi4ȧĘf&Ezߵq0uIլ|{ oײ^+pN_7n]9iśWctWpI…Mq2 Cdˏ/,! 8=tiӧQVukׯavm@vm۷q́n߿u'(N%WysϡG>zuױg׾{w8HƧW}{Ǘ?{y׿ P ,L@ l!PB 1 9A Q=TQLQM\aQimQGq R!#,2%lI$|R+*2D. S1w315l7S9;@C"x 0O) 00d .P?C IAx (85 60Q JA74N5J][ K^(K-5eA`S,C)G=Q/&x C4aS" ` "[qo[P6R}V P/ D3Z]+z-P@ւ7N 48^ NC&WNyu h$*~ .x4EZi0xu 0."TУS2Ճı 2@dk%= Y3oI6!ycmqFE - USmCg<t)GQr^uEOt>gt4@8 getA$vc^ODML%8u)`^5g>A@gQ-6tT 6ڸ0wa[͆3%Cfߙ z ')@v泠DmAR28(+ 8N|4`,T~rYmx3 8M ]BJ_:ml*a42iA^u0)ꝧ `L0!j ZTFV\ 3tm?qba4#>W|+QqG,>$c.)QɤKrDukR'Y ]턚,ŁEe`8w A}SppL}  u(u5](TlP$`$?aᬾjq}q{Nt&Oߓً7{gGߩѷ0  ': "=[~A~y(:~7@?.N)Ab `/L!9@ a9|acj"9 < "?BP#-` c  @ ֠@9@ @ &!<@ 9?ǀ9`  <G!N,6O  @`4P  "4` @C iaE=P6PF+p[3y" C*pq٢  !4fQ4o C?@8` `= >  q vz"0 1p /d(j"  q P3ȠQ?   ,Pp @pB8:@ M+P @ |#YQ(Rˢ!(p Eq$?&r$'B-q#@ `b!=P>q/2@Gq<wCma GC|r R 05)W k=r)G2""p "72 lP,   9@8@Q(y3bg24&uQ4! :{,o )0 q!p'A1 2 @ FpNr*b'`o-~2_P.A 0sG29ʏ>8R9!%2 b9,jkR?o9Ƞ "-4s$; PR"p q9a!?_+0$s{m2;(P(@#A.#->W0 3)#14 E"%)i Q$RK;6+8sJoԡ7|!,17=2- A@@8 QytSN$ A @80-2D1 )8M!:NJYܗ|e!RxN`yA  iOy1t"R t8Oy?8`vBx,p?xx*ЌU3K/7.c) XdQ  $RkP5 0>67HG!`O ;fAj"b &b Oyc?@3q) jXNyVx$xS b+` ) JӠ !`&1r"v{T51*mI/U}G}Ud; 9= Guts(`!9@a9Ny 3x0]o9R`uqkxR~-QO(v9.[A4Q ~i1ykGWsn%aO* d!ra8`P u#5VZ9"ww #`!O*8 z0 `xڧ7کۚ6Zǯs7<b{CtVnQSp14jڟ1T@ 2Gdѵ:Y;`1&XbaKּ M<׹xU{&`VrӚ7U/Йz2kٱOӹ&j@|)zoGRg~t|d- j:Xy%ywEÏǹQ*; @sI#bo J'U4jBo%C#-@j7Cqtr_5Q{T¸+<'JY ;CC`d[^WqnwA)@sO_cx;+\|(dMh+ #=o9_:ڏ]Yۇ=}͵'M]&}Mɽd8vC8s~ 4 1 >e(LVz7%~)->5~9={3E~I5ޙM>U^]Via ܷ}obgڝ&Lr^v{~%~L)o^h[ J3aA(| `G#ܓ9{'A(H< 8"<3+{ ' m`D55\9c <F,,B^&!?`!w ["; `G!`!3-Z!纋ݢ௱#ߦD;RVv@ ?q4ЇzF0׀#3Wi9ڲ3EY?C-> Q %|*&'!t<c nArA.#Gitf#eu"&*.26:>BF-,$|hQry8Q84|0Hq:eQ%y ut29$8|4-n# dv\ݾ/*|pX^N5 k}|$hOKr0r:p,| l@ad͒a< =AIʨq#ǎ(E pkHmyP"'A.Q,G ։CKZ)̙%$z"ܒ}bgK{^M+UZHubu kFD@@ t 8d88%ܪaXq0A&)lJ:`C<0VSb$ˣuzMYA`2NM Yb/]:a˴tD9B@ck`vmy~GR:$R{(4EQfJXQ3Y@s ȃ[0၇XG+=UܤɁWX @ y@66Ďh}`]e htG@bs1%6i(eRTM}N!滝h2ӄ!e)h7;51k#HOW:L rvW%tɉ4;T r$z)?\a|z0$kkO}J`a&Ā̪:01l9iAȢH(&Ic -GwoeQc h(j΃>:1y.Q /K/!>gddB9 dljpҊH Ug^^%` Ag 0gJ8E|2QVV8k:N NχtT&OXÀ$KRdy jR ɀU B^ɘxA@i@d* wpri#3c^przf騄Xn"Z1B=QsB/y/9(з.B`6x@8q|(4l'EPÙ@YfB&`pxc5RHʱ>K ܥ2Sˁ|WXƸZ |b>ƤȱievU9܆, Vn]3VBw*-, B-$I#cƜ&҂*- F>UsЗM`Q%9Jgn"iO][GeTѩoxnz Mّd/{rh㐹.؃|K3&hjyxW0,d^c{EV F?i\jbFؼn5F_4ٴjw&HiO۞0mvr Mz}o_oι[&;<&?~ 7uSbJ Kn<*_9[<29kn<=C>1Zǧ>mMtz?~8 c"z^u:+m{߿rY?;ӎ=^a{.w5i=dv;^<0*aI#NKCv>x#_|~}ے`/׏_['Xoo"7;Gs֗:پw44q-~՟iqDyL:Xݟ U_ZI`Qjy`p`nvN_  a|` BA ܩ  ! B2a :6R!D 2Vra!fa v!3kƴ3:pE3=Cݓ=*%pݏ #JH]|.!c"6 ](* y@< @#ĠYl^B:'&(:D'r\:0>d`Y#WԀ,՚۱F"`'X(hu8p)F!F & j0D L9Nԍ‡Öy,iL ,a>[@J|BBiE6\7c՞'8,qO`6y]x/NXI_tGlp]DPFni`8Փ=0= &,H>d@>A$p06PB @ $P1C,A R0(,C ‚:H@ F6 Y.Ci0)|C@* `T h3 `@ e‚6`"A$`$ fUpcilzT '.\M7@;PÎd~6-.j~ B  6HPc 306jL w\K =ˆ:`‡!X:,`/HsBX!7fujlp.P 'dA 8\@*0`4e @u ;0@xP '?0b& K$ *h@[ @ D<J>h*AcEb J@#E6*9CC5#xiEICh@`p( 5$Ӄ1 !̰#x)>*<d;=0&B yð @uɳ\8=$P<;A#Y\7ϸ@D^A"a)(@@ H F K`H@fT%C'ځr )@L0!M@>/ r ЁT(T D*@f؈>X@6 `(JS|\bw&~h x,Q5bxO BLM! :Gl=xG=,9<4TP"p0uR' #at8 %,KR6+'%=Hcա)[$>8R̶Q{@t@`DLp:+c L0#B&nC H5n@N1H!xIw`z^@RA A x(HԄT0PFV0b"&%fGi$*)UPo$rd3(ՠH/&2'Izpz@ʪt/vX]̌4A &\'Be4a H:g| [K k b@cfh܌a+D2hZɪ v` AMF R[Ț *P L@fB訆 "BaK tIA)Lkz 7eVT.Tb4Mkp|q 40NA0^P^ZTVG*(+`X/wG8׸XUTP pf\ aъ l,PL 0q ^K NhFT' Q.ރ lȁ`T"lJ<&|!JP@"|;/Ѳ2_Ԕ >1loFJ-?A2KRP B @C 8`$9MO/+@?ڠ#d#/?4p pJS0(-r2\vx"wun  4D~FQHA!hb$&?V!6yb$Hnb>V%F;P"a5R׆GY"H5%M)b8p b09e [ x+PyRH+FTr~GK1 <q4baF[t a#,r7rP#-A@3@0&@2`0+!P+EP0f# 015m>- r/!`4`S7B! Ў>:' ,4 fD-;(J3siF9m0'Xa @u0Z60Pmape``By&t uP#4QZ!,!Q$s pPQr`A#0'G.  0 naFaꀀq]z nrk9 M&e mV +I s9Ylƹٜ͠9YDֹٝlƊ9Y 湞ٞ 9Y>ɝz* ڠ : Ku # Z `&tI0Y `Z` "=Dp)#PEU "`(? $`!N2c cR],DX&n[ 0 _? # &@8 ;p% )0# )j$0BU39*pv* F+`.0P<&v `C& RX60b<@$z4@h R `$z@)L-@F @T L;]x$f:`̣  @f,pO @,B%8wFw%8 Xz8ipSA#. @PA$4 %<sJ¤uEG@&T @P\ $Ђ ) < sZ5~F!4 -:K 5p9/` 3R6Ƃ '5  &PQ<@. "ʩ0^`<e"`K og $Ъ?5Y2# /fa4S )`*0PY:F.S0-@6z jc ]t*GnIJr%h?9R;86)% > f0a 9d6`#T0U"D9E b 3[anѵ<볊r '൞~ -N;OS{ U+*1XK>p- B@Xcej3I0f:dָ -\;W$Zꪊ|<+@emRrh(6 AI;$6<bJ )26%N`;j~A-`2-69dkX[ MtJ3PA#3@F5ФP|  "ਙ,=KZ<1ؕ-@ `)`Q  4p&0Q `F9'p2\$ӹ>0+rmiFYpQ,&J(@;`@  .0+H[ʼn]#0Jx[hla% 4Iq|a00zRqٔǔya8> A30P@ xl $qW-7Ɏě>ൾl4 = h@ z 'P "C$`I't~z8r;9@G},L3гN=\-9du;lc' ,< )& >P3o4 лg|:`:`{6RTDT?<31qv:jՙbDDk TP-^HS6:%w4-%ó vC#^B#o"|͝(a5'ONb|HlVΤJr"box|prD"J|4}"bp*k| 2}Nn8p j}48k O4"pd \J» r J  4e}V^᧦٧L|豐!Bl@B1fcFHD1r'9peKYٲС7qb0r 9/BcF!x B>X(NfrVa~%ZSlYU iQN]jǹEVI}M0¶oJXxP]2>W1#9VvYcd)|fs=X4M߶jݏ].[7%Wys "sױgO^` ?~ T'^{4 a?~ R~8" LPlLA 1lP (AT! tQ0 SlS  `F ;` ? Mф" 3߈,$112!423$k,r.(H*3,Tk4q2*0 3H2424,k  6``\`Pnx4H *.(  6> +~m!jAo \0i H [66 ZI!C}@^-x 8]_n"PF "РP(!up ^>W6:8Xx^-eMj@0ЃxffMK"v  ^<5 &p HA(A7 Z.P T#Ѐ &.q P@R`ks T`@&H@ Tq@h @e3I TL@-(T$H  hR4@ RlHu@@G>@<@$0!P~0!P"@փ $ @V Z\A<"&l=AX0x@$L4BPh4S0|PJT $, 4XBp5eXM@& HbE, 6؀-x6L;0^Pۙa<$P 1F(4dfta0@ .ЭT|g!qud3̈́Dz``L =KrAYP9 FD6PYd,`HBЁꥣ>p@L` p P:Ȫ*/e R!ؕ6`gRB& KUv FJLA`JJz:`ZV(R&$@T T.@`m(@ =(@b˿\)0yT6N]cPP@ӌX hX-Rpy)IۄBA$0`SB38k;@4d1@ꚑ 7h" x`0PI.EA 8< ?@޽|@|+QZpޠ*pKb t@9D8+M)b((f pL D)|kňbp@/ X+@ , A05vdtYHx@ &A R̛s1Re,ѱ@ 2` Eײ-]j OH8pBg 0P&@eC0KDrCŲZt4+(1ГL]`83!. `er32vQͥrEh 4V^hR0"ERH t L1&$^4 />]H @o88T. 7D Vi1pSv }_&f Si8`[:vx5m'44eB>-`H tB j< }if6"G@Fp^@ @jFbj ]uЃ5JC '-`dSQb@Q%f*OrE> 6@X>`8Չ> Vg*` X n,S!N@r'2EQ-:%S@ va6aVN &QjFf`\b A*a!  za6=8`K"@#APa~YvY8 r`i܇Rظ::d0Ne~Xkk@(o- )swzUWU/p=šuuC1d`>V@$Sg(+) r݆(60|-jbk$\@_ yr xNwOcI 7@qP>@%@v"):T`s z CyQot@ F0:&vbvѻRd&vlE`X"7 `$,rOrh< >/+|~cI2 Q8:&C [@l`FaB Ceq| dT]yJb_E@ l@NNI`\vn\ 8`@>t-2)u@:u8}<@B L(Y1Z܀h`F@vY0;{iz@ o&5[/Eaw  !-Qrhn,=D`@xz`Zo e:`c$@\8<\4\QIZW| gQWx Nv`,sO, R;I5Ǒ@x.h=U`5\Ah6`h+]cg3Ą_‹^!4*ܜSH ;2`P Xa@IYUxl0v3~->5Y^=3?7:5b!zY1#ey#|@n$E$DdC_DHDEV$J?AdĄ3$GD?ᅣ6?#:C=;< "8"%| ;b-H.lF|&A9=qL 6:>I@VBجXnrvZj0pxVѥn&.IRvbj끊o:*2FV7bows!+/݁A?N[^iyo5w@y;h,U R'D?x.] ৆@7=480@ =FD:f u;x/#mP$|hJv!5PZH#MRHlG)ǔӖj*ֈz}cBx? m09%7*(_Yi@@C # }xǻ6er҇#;<8Q =>@gjfaᵎ= tGM~:R)Zfk`9P,5iF^, * TWL~g\w@ $s'(ѣ3okPH|8KV(D" c݄bΣ>UGE96޸ l 8 @[ |w0%y 8?>Jk٦yywyV> {D Z"2ڨBRZJ Ξ= ҟz4!ڪZ⚫!Azz  8E@~)Ȑ9ܝDv t@ R +- pQ 08 ۻ,+@>` TBK[4PA h`H)L^w[C$ x3Xh`  &8 >0i p@V<&K&0@,`: db멀06A `` 8A`)xz x0@ (a*^ @ PA, eTp L,m/ 8!*X#MLTJ(Pl`5X 1:~:ib낏* ; Ǩ@ 4%ܠz`- @vl t@.h@ (``o\ PS柆MI2< ~HU'0<Λ`-adlK@f<=F9 P:}  P 4h=e|(^QM*`x4ugSr2#&@9蠿v\@t<`L(idm +!7L2I(s0dO(PDw>_3]fCܠqHx'K8T 0r&y9$~&6Wv h;QAL*J @Ё  @S$nD`!k%*%G]!x!]4ݽ)؀ `)A:wI`BjPB ~v` `_Q}H ɘ Ǵh L$4H X h xÔ83DpapB L@@ Σy@:( XD@X n r@Ne OOW"H:% @YZサd x@7[`ԣh t @ @@Ԁ>%\@jB`ddrLemV' op q%)vVsWDtuevu xDz{aTDS @ @4%2@Fil1؋e@ܒ;3Y@y:DĀ6@J{9IB@?m ģ ̣@ t d?ޘ@؀`IЀv zDnH\PAY$q`q |YE"hQYK\Yٟud >@(i.4XE)X* @}bHl'1Vat dl@T\ N @`vƂbO Uc>&-h(Dab][]퀹톻۩c($?R=B+# P Xk4A@@\@q t`4]@ wU&kM_'<@g՛j, |Z7eN @Kt@ f㰐@] 0A ~-l]]s mqH4EP:`ލn^^>E0HV(@ 0 EM.pN%Hu |RYqWW )B) P QbIT Tz 2T j B$j`&  g ' S& p . Ӱ+ɰp)k`?B+2:1\pGqkM1V'. qqqqӱW*wr r!FN1d\1l#+K#g C%$ %%c'S&3 ' (-1r +r,,r--r.-4. Np2n#s2+23s3;3Cs4K4Ss51m@h5ss7{7s888c3G:s;;s<>s??t@ @tA0@ Bs6;CCtDKDStE[EctFkFstG{E; |HtIItJJtKtHtLLtMMtNLtOOuP Po4OQ#uR+R3GuSCuTKTSO?uUcuVkVsD_uWuXX754YuZZ_Ќ59?4 % [_vT'qQ  PJ?*C|>]ecvf4 @PY$ @`@ @ @k0 4@X@k@ 6vĵf;sCEoUsg0@Z @ hձ^]āpA, @ @ | tt896pivww$xx v\LE@\Xv_v @n@ ̀O@38uw TD Ϡ@LvLPxk9Yܞ` m`Zxx_x&@xJa,Xy[W KH-WD 9ArzޗGEB 4@QX zUzFzTnSɅds 2$bz;;NAy1:Swh@x@CI)Cͳ{4 ;̀  lHS ̝l3X D@d@?zAVBSs|6O |{mU @@nP@@o t}L^T0@0Ƒw|K}|i%JxP;w;YQ@TUU?[@al@/k@;@l\~ id}/:_Z25ٛLUgx (= N6އ{g ߗLE훻 (y @8mo-8y@M>-1@ ]2@ #<\8k@ `` @ 4@|9T@s2CåqxG9N%-5SL@|sz~{~ $,4QD-^ĘQF=~RHOEI-]SL5mFpհ}کgPEzTRr6SUzUuY~kXe5V0kݾ\ś7]}j`… FpI6Ydʕ-_ƜYfΝ=ZhҥMFZ=plڵmƝ[n޽}\pōG\r5vAխ_Ǟ]vݽsgS^zݿ[C )_~Wo?D0AO@1A 'B s>f"C? %Qz4 R Ԡz`r%pn#4@(j5[j3Up Qn gy W)pH`@DT67b|P@0L` e X@gj| ><1xKҐ f0 ML2o2"Ѐ2l@*[| I N)N601 pSDQJ"83 Lk@tlzt$ShL H "%1`~A8Fhb@0 6$6D P#L0,f  xJЀl="T`G ` Ёe2Dr:س=xU'yi`yyhFD AHJ5}7M>&;I%c)׀OOLll^K JT$Eǧ7&$bFڌ2ȑ5Tdis6D쥂U]B*dyO6'"CfnIFVT3 Y6_ۨDPяp6" () bڮ n>plH<@\:Oh##<@ZRTa0 HL` &5yq+H=p@cfH9H.x E mLS AR@ 0qQtaY a*p6ruR\@@)> @_0 m[a k +he+> UIt[nm2GåHq61{A&0@NMJ4+=@cP)p6_9cmZh5kÀx0gH`om8qS @ <Z @LV V ;ODpռ`+| ;+lv 0&@^-%uTڴ6Ț]F|rȨ(E(iY5on[-2/Z mdWi j9()a2@‘ֆt 飡6M̝vDƼUE͆~Xe? Sߍ,QY=[qd/;l~fh|O'3!jaŜx"HaغU@xn@[)SЙ{@M"Wrnj1xZAE1Je[$gR4 q23=E&6RlZM"DFo.Y@]!SV^м%y~$3M.@S*$ŧ DZ rj6`yaЀ(PX %2X88HX"hjAj pTۙ Tؖ "P`# 8 A?UbGSqxm1 PTz4 `/A9 >/AiP> )P ES@j6c o 97C %`HMLd9Vd,05DK EoE )9T(1>c.D[/SijL@`mnl|mq$rt_q4udv ptutyGnfz}t|ǀHGfȁDȄT\TȇH`cpȈȋ48:(0T!H,AXCω 9x5 hȁ @@29?VI !0 I14(;:A @,@I xS؀ &sDIbP>%x(OxC d)9c.(HV*v0JM Pf`K0! Y˶8 > pUԾfƼ"ȰmZȁڈXt9XpH+Ϣ "פx HضSۉ@N9h 8 ؁dFv X=Uၫ i!lxېS OhM O\:4P$*`דM0J x4Nč' m DEo`PQlў(,lQ%c;2R(/K(M|R.R ꜐ :23GRrl^PP!ќU*ِPL+@uOͼpِ&UvjMf]8+y1V!UP@T^,W|Y\ MQ#aQb xHTfE}M09]Q1@,M-EK&p)y@c2kX@fxMpJ `T  1 iQ,HOۙ j<ވfm_|FF],kQ__r_wU*dNe BR^`Jؖ" p@0Ip]p{R+N XJ"*lX8<$QpB(`u *F08xc0]dHa(0 `&GT➍ 04(Ec$qBU`ȑHؖl!E H( `12ix[Y87d3O,T0kJ^H;B`x%U8vHgl&su8@@_ɑ 0rۜpl tx0H3 &bgM @$I 5# H72Ȁm],gL) wqlvЖ:K\qˀcknPK": x9tˀP 8i 0tbIH=,rp@@q~v:C7֠$k> G` M G>z'4upi LiULDH5$C탮PoxaZH# P6{p ؟5ODrGʀrjJwQϻè3t5 X9L?O  HȦoa -&NS| PEh& &|,9V䁀2P23@S`@Ãi$CbdCB21p@11p`䔫3aABB0!csS3В`R4@SBp1q4⃠јPCD80… :|1"N8i`Å9%(hPъC#`S h8Qc$tHA 0!=( 2# 0%cƃ)|pC\1#@G<4a;&D(;GB IGuTP[CE%K!R ,"hT j0@"1:0abٴg|\-@i2P`ㅈ# r @?#ݺ@ǀ#t̙0# @%ڿ?C`YI4@G@ 0Lp)00H@)d0;-C@<9hP  @ ;`NXK6Qu 6 hp*`C&>  Y UDs 4|P^Gx L@r d"<$4TD,. `!0A0 0 %B>mm`?$<:lp 5fpD#dЂ>(<! P;0 ,'x pP W~nD]5@K (+ )@ vD @B@Co;.K{ O4pB=Ё;@>A)*a  &xf ܸ )0p`'M X0A B .a 0$dP ! 0COL. <b90z33 6B <B` z@vK{ q0@p0^@!>#lAo.ж0B 0 e_ 'Xkϟ90r !.~D!`A: B  d~/.Ёi$ E L.0`>n[.\ ; ~+` @Z:/B;]lQ(^zSQXn|THh 2At#@*cl:ɘp`J*҈zNcO?2> ~q4[%DPj"rDRP-cG. eԤ*M$2,/ N#4N\&;I9wʳ*㜧=}qtS"';3L&A}*!<й 44(EߙЅj! mjQkM4ʴ(Iэj7K_ Әt4MoST`@N Ԡ  0Ԥ*uL *TUgZBGvzTJq;ud-YϊִulRut+Zנ ծ|_*oxd-a[\c;z^@4)e;iJ4ɂ- 3kNlj גv=m=kkղMhqMnwޚ-mqCMg:W.w7EQͮl6D xkG^Кedk_sr茯f0_n6 C>NL֦;< [8?A {ĻowX)Y 1/[cM!RA|#y?=#>RJ72e?V9{^3ikۀhU1p|Bc:v3|n0a#–bH"Bbi F]rlΟ 7sq %e1RN?tY@֚ fmD̓7\%ܒj';iܺgZJoF"O*6Df˚9|"\QF=<VQG<4(j:rpIlfm+pԑ7nHf1_<2#WC][dI_3jyuUfq P8HC>iUD:'dmw`o da40V3mƚhm# 1n% XH$HUע[?bc$8B)%i5nQ<݃I[fYE_rWcTyW(1@h>Vd3&t%R)[/JZT2X*Q Y]5YnnX |sv<x6JI7@jco;6{Fˁ_>AY؀B HP*86ȲFb.wHZ6$kmv0,gxn%z<[ XKYlxsn/#i8_ІH <h#r ˋ;B222~ 'f)]%Ёn:+ ٿ5G$m |G~fAw,|`&#h6Yt- ]&ypf]$:f fHmfRS;A dJ (0!tP _.rݠhw3@z$j ߀SF.iƐgW7vưۜEvfk$fq"68˜]Vm`4pfpt{'H|NFRsA~|D0R#@2 @-D|C|]y3U:WS-q#YPh9EHFmNٍC1^[(#aP(Q9+FH :0fZ,5e1b˪Hf1y3Y!ɪ4(W]oG7 W@5TΊk ̣6-GV3А$|ёKmAB@t3uf蛙\636`S0;SgxI@k.v<'ͤt/W3)ܶ52}rPAvWO)tQ`pmYd$gCnj#ְ!IGudh.BكhT2l͢"q3,aA?H k!ŌE,AcSe{f#b5cH2iyHNwmSUeZ@U аe2HdMhpjeZc_8Z4H #niV0ˁ2J[r{W׵5$Y- &5PF?*"-WH*IJbl ~*.c (D#jގI$e nns^JȀDފ3XC,ʤ8 8DPp-5bhf2!ADbZ@-fqSRt58αwL @2@|," 2&C7vLeY(Xβeo`L2KyfN5,n3L{ȹ"50{EL:к5 EϝO!N:HبC3D61:reXƓ :`_J@'( XRNƱ>h æ>e[g;&Z|zJ*蔇 "ns!fEX-<[,%)ɖ $fLDb{Ҿ ;m;d2^qdњx bkn]qi# p̌5Y|Rb{[3 *@:ٮA"pd jҬ$Ζչi4^SmHao{a1bCzn<:Hm!^z<)D-7##^Ij԰!oD;?sH {z)(YTyGk66fu m0d~fjytW7!8 +0V6L!yҥ@W? ${!CL/~lcL D`4u6} ~|΂?v.pF5'憃VpcU6kHLfV!|XT=W3 ѰQoXe4EmDAȴ}`~СAQE's0M""|I!5r5Fwf8 HcuMipD-۠wv_[d2C"1 Zu[@E;3hU'oX;5_=|ђB1g06vzerx%nkRy Q(bN3 Li0?C13s]:-UrGKJS}NQ.;Ѹ_H#H~g']zes:qqBh%w0 D(4ClH;ו?w,V>7NS%sɁ'v-l/S@= (& FC=P q$W{0cNP IBA<9pILmXBVӷ0+9ƅɂ a8~A2bъ$+9qQwsB' 7v,yhw:|B1.ғM9AU5'>FA8x@a@1QHq^/APxh0Zgb1l qqXhAYz+ VCwƠ%\!z}4_1tf7=16zڣ:!1i.a 9J`ARʡ\_ vr_zÀ_`⠢ 0\ wv p tv |zdaj Y9dZ  *dJ hj ʨ j ZdZqZzzڬZtMZz3غʎ;WvZip(暮?Ԯ\֦ꨠHꩫYP0Pp <ư@`Ԁؠ: @`̐lFlᤗ`X,k z * #YJiA< `*X 3j ?:pi:?Q`6GLzɠV0 Q622`vIC# m' rMcu2qe(tbP*oV*-B+v_+S@۲&V. ` ;7a3Ah g[4g*x7"{_kvZFU%T B Q63%YS$2b RA &<8m˩!D۱mso(Y5fk&;n2{Qq k8cH]{ k""AD 놋b X(7w @4cWw,ӿ#lei&&dEy^)33 rpiB4*o-a%"+BA4J ţL:2DId%9~0lE2 L)a.i Hqk=SF8S@¿Ck88 mt "HRɇ%Q8~c7T ôgY L:ʙdmr9!8-E8l98 r;}˶nH<an0Ș13bl8#NY,rL| ~j Qʋp) xV$sʴ.üIt\ 8:W댝?ix b079e[1l*"r/Q}i ZQ{1pM; #ҙB.8w" 8y>d>Q6Q<$dzAa8$$55{ `=ˡget5hr^!Yۉ1 ]j EG84~3W{$l~o`:~ V['=X̹acI$ y77880 uv, %>qS5q.(Flpp}!]=З&nXSr4D8jpzc.+44?E̍PɄ3.|vgxIބPw{RB'“!䢁}ygB=' 5\}#_.7sx :88 ,<> <0"I-UWYUT  &?:[v ?{y H_ڲ9 8\`).$:U! ءC* px1%iX0RنSn@n,bxrLC $$hRODd.),yf$`æU?\%yeUv=UY݌. Ѵ  `AvE(a13%<`TҧEZΖXN-[oh'вܞ7^-Z8kş^Frρ1ǎvVԽ+'@x\ߏ֎\w,£ q^i>ب \±\m$l 7Kc6P@qY B*qsΊAp c7h% B$pb D@KXB\z>^l{1c*P ϼKY.|1+Q@L"3҃OĪ=e>w` 2QꉊzDaL9UH 9aB 7/eh6 7 J1+8r"N! ӐQjmNQXbV.DREk 2X0Ŗ/Fh` GI2XqCh0py{.xyyi8QtTwoWiPp. @.&MمE$%؟@UB?8 Y2i'j#y夷}{er'/|_o}7~C/3$w>~#^WrƀMǽy թ A 0 QB+t aNA5 M( pDPE:$MtH-Uȑe]bE1r ј.Qm<=ρ tDBr OA!9|$x R&]r`FHR^d9mSyIR~ %Ir9nHyHSn^RXɼX;,9jL"R@-⸒D0 A;]!GcM279)9D4cMQ3{شMs ItjϗL?<|! 2L?ˑ\! 7g'3t0Hx6 !PgB|E)> :hea#>scRd &6]NiSY4S Xp9d5 P>T*fM3PZ/Z- oꪷ )jsSk#E k 6eUHCnV:l Y^uka[Ζmq[݂mi#+諥`Zgu#kډvϵ{I*nphuVr^}ݩs ""@ DXB+B EWMP[/\1 K_.8 A૰$?aS; +X-ReyeQ4aJU권.8áG1'/#qr$*hf"buTPsFB/dILp<y@sU)TA΃t ^x R< ڋR d2ÁHc ! KFw4v4rS Ԃ`dq%qZl V1•Ғ2/tMh-%y0n.#puٟSém_H%kŤ0SQ`di ȖblRK֌n1m=^~MB$ 58:<S<@hP%Qu!^A+\jPa.+#8.ԉd\ U{>]c"Gӆ.P[Νh2y]U3[iby" n[{+h7c<P#Di{J{(Kv+P3JF!`> .X kPm6 j*JJ0AJ/،R"laM^af䎠*$򊫼 脋 !5iAFR+ OMln&m%j0Z&DGҾ`*者vGXoGT  L0  lDar&r|p۪2HK@A`iXEzx93ѱ0D:Q'H[Bb'8j-TB"L 02*TbV-i)A$pqb0.B~BC$/oX:> *pꞬТI 2eƁ@!*Hb 2""@2Р IHXO$"fK1O~l#<:-@-LQfN @xe,J,(l1pb D`܂1@$>BF/*r C!a6R=L!:ՈK9%@؍"vE߈HA$T!) @n.E&l3n`ɔn5KRJDAPeFam$tf h`.E$zF+ฏ2{fR舮@fd6r l,btJ7*!.>udxs>2mY@2̈+rP>~pГ .̞Pq%m` O0 󨬥8/<. @7DBqC$Tp8D :S?NrKNnHha$rﶥFo " 6RFjGSaXLPtT4ߍ< bTЀh or aL o t @?>f8qA:e(6`Da.O T3%/;E3,3=NpoWpP.YB ` 1f?pt0SK\RFX[k  05<%$v5 Msae%AWcrb1ִּv6cEvcG0c}UdU)H:v vee&M&Cvf eee vhhh6iviii6ji%6}vэhkhvl(Ȋ1Lvdv;; 5v0ְrvm3gnnOnnpȘgqCqqf>rrGcs sr54<:@Hwt5u!u=Q8(~C,Mw)f+ouvxKHx7yxyyyyzJt+{Tk{{7|w|ɷ||FHؗ}7~w~~~7wjy2x 8$ 8%x)-185x`=A8ExIMQ8UxY[*#eximq8ux}8x8xx8x+8xɸј8ٸ8X縎8xx99x 9y!9%y)9%0yjx4=A9(`'0 Y]<,2 4s& @2$0@yyc=@0F4 n!2."2 `-y鹞9`d"! s`ٟy)ڞ=2(}15=zR;8c`+]/2$ 20~ >5>~!>%~)85~9=i}EW56%yizM~d;Yci^&'ej~9瑉e6qW^>x}";v#h70 +QC+t8^z99dQHbhufX 0_rZF Q>&J6[sRoΰ:gmh%PhĤ$ ႔sRΰ>& '~n2I `T}'K^6s2!)uR Gf$ @jdġi | ,`# !.aQxq&7 J.Me.Xx6FG`z45íF"Mv/Y*@ {!]-0RO \dO:dIZoWQTv΀xzH.'s11@ Ti93  K:mNSZ0gW]~t8qtn"O(즽$+S{(myPw!n)%.rəchG6>p>L.E2wVx "jX@ 36Sv6G(Ht9c;~%FL9뙤 ESH$!!]L0EPAS,B]f) e~A7c"H'Db 3b5:UQ{殏2B@h6t5n/[uWo).G$@`APFk `q49>wqc\R&p_ kBІv# {0B"hD0'B1A &J1Z"cHE+QX"h3a7±j\;1B#}hG=2$ ?2\p i"$Eܤ-yɼe! @BNdDe#I6v`d ݙtbe 8㾰'O%{}>WO+FBp 84 o>#YI{'ֿ>RvG~Py?U%yEe_ ` `v&`bQB`IU|ŕ` ` ` ` ` ڠ SZi +E`= .r BF !* aF\rRJr+xᵁ%4i-`T6,DSߵPX]><_2Bt?!QWZ) TA&އ''MG@Z*Vŝ&0*@C1@-Y"&" ˜!$ %6VuӌH4VxS?DBUA2xd* XH`OK(A/a|JL$$0CY7̚4|εHԩԨ^%D.u KŵTW(T腋TT3tfR\XtEZxfF~WA1 !"Z[1%-2$ZIzT[-X0=մv0n>(KC.Î@!謈ЎA4D]R#~|%,J)kJ .%,GU/Zs:,k(\X2~Å-'A}xU`U7$ p]NDb@LJJhuNjZk֬}64pXĖn$E6A#8I%nJ!FJ\]Myh]g nWxrcI܎ A0ɦzrdAHŖ4&TBds،%\a46|1΍.>YD\1BUFl60 6*XYVD'/}HMfIL(!F%('2Qin}ІqSM?W4ګgT Wߜq- I/dX XK|XH8fڌּR}pE~Vܝ]p/K5ZJMgCG+kJPjB(}> ~DBlR%HbIG $J?q bKH:m0/x|} hwA :D ($–WOT''I-pVS$ v,3X׹4ɷI8$(2(ݒn1y Xg<h##lIT"/ A޷J&BuAS6FV0(كWLD{T]dW329;\NWIѧ}̑-y$1Gg&s-U%gM ^-ВHK)Hhk0-F5-C}(c. ^%[%thO-4h/05 s2 i)EO1U ( K.7v=6-ѐNRfgQhoiKj{j kۙkkl3lmWmOngn/oo' p7pKq+qsrr["9w"A&I7}E!wwxxwywzz7]{w|˷z|}{vW|x x\#x+387CxKx#[c._uu3 e&qyt8]#)$v6͞ 8%x ͸x x%xI8Fhc7яRKR#\K}uu&m5{J#&%] !A9Q9#Y9١Ϯ%x~+y[7Mm+둟':+N+9'Ҝ;Y09k,~e艎: q:{4[/+w`W¥詣:cz{ptwa7yT{|TaKR(-9n5v˻ER{_{:b3|/|K|{c|ks|{ǃ |,L @|ʫʳ|˻||| +;PKpOfNAAPKpUIOEBPS/darbbook.css*/* ========================================================================== */ /* darbbook.css */ /* Release 0.0.1 */ /* Last revision 02/07/03 */ /* 2003, Oracle Corporation. All rights reserved. */ /* ========================================================================== */ /* This is not intended to be a stand-along CSS. Instead, it cascades on */ /* top of the BLAF CSS, providing minimal changes to the existing styles */ /* in BLAF, while defining further styles for DARB-specific classes. */ /******************************************************************************/ /* BLAF Overrides/Additions */ /******************************************************************************/ /* First, we need a couple tweaks to the BLAF CSS. */ /* H4 needs to be weight BOLD, as "normal" is too light for accessibility */ H4 { font-weight:bold; } /* BLAF doesn't include styles for H5/H6, so we'll include them. Same */ /* Font family as H1-H4, just slightly smaller and BOLD as well. */ H5, H6 { font-family: Arial, Helvetica, Geneva, sans-serif; color:#336699; background-color : #FFFFFF; } H5 { font-size: 0.9em; font-weight: bold; } H6 { font-size: 0.7em; font-weight: bold; } /* Loose the H1 underscore */ H1 { border-width : 0px 0px 0px 0px; } /* BLAF doesn't provide much contrast between links and visited links */ /* so we'll add a little red to increase contrast. */ A:visited { color : #AA3300; background-color : #FFFFFF; } /******************************************************************************/ /* DARB-specific formats */ /******************************************************************************/ .bold { font-weight: bold; } .italic { font-style: italic; } .bolditalic { font-weight: bold; font-style: italic; } .codeinlinebold { font-weight: bold; } .codeinlineitalic { font-style: italic; } .codeinlineboldital { font-weight: bold; font-style: italic; } .syntaxinlinebold { font-weight: bold; } .syntaxinlineitalic { font-style: italic; } .syntaxinlineboldital { font-weight: bold; font-style: italic; } .bridgehead { font-family: Arial, Helvetica, Geneva, sans-serif; color:#336699; background-color : #FFFFFF; font-weight: bold; } .term, .glossterm { font-weight: bold; } .glossaryterm { font-weight: bold; } .keyword { font-weight: bold; } .variable { font-style: italic; } .msg, .msgexplankw, .msgactionkw { font-weight: bold; } .underline { text-decoration: underline; } .superscript { vertical-align: super; } .subscript { vertical-align: sub; } .listofeft { border: none; } .titleinfigure, .titleinexample, .titleintable, .titleinequation { font-weight: bold; font-style: italic; } .subhead1, .subhead2, .subhead3 { font-family: Arial, Helvetica, Geneva, sans-serif; color: #336699; background-color : #FFFFFF; font-weight: bold; } .subhead1 { font-size:1.1em; } .subhead2 { font-size:1.0em; } .subhead3 { font-size:0.9em; display: inline; } /* When lists are inside tables, they need to be more "compact" so they don't */ /* spread the table out. We need to suppress the natural line break in the */ /* para element for "paras inside a list item inside a table data" */ td li p { display: inline; } TD.copyrightlogo { text-align:center; font-size: xx-small; } SPAN.copyrightlogo { text-align:center; font-size: xx-small; } IMG.copyrightlogo { border-style:none; } p.betadraftsubtitle { text-align:center; font-weight:bold; color:#FF0000; } .betadraft { color:#FF0000; } .comment { color:#008800; } PK*/*PKpUIOEBPS/adobjbas.htm Basic Components of Oracle Objects

2 Basic Components of Oracle Objects

This chapter provides basic information about working with objects. It explains what object types and methods are, and describes how to create and work with a hierarchy of object types that are derived from a shared root type and are connected by inheritance.

This chapter contains these topics:

SQL Object Types and References

This section describes SQL object types and references, including:

You can create a SQL object type with the CREATE TYPE statement. An example of creating an object type is shown in Example 2-1. For information on the CREATE TYPE SQL statement, see Oracle Database SQL Reference. For information on the CREATE TYPE BODY SQL statement, see Oracle Database SQL Reference.

Null Objects and Attributes

A table column, object attribute, collection, or collection element is NULL if it has been initialized to NULL or has not been initialized at all. Usually, a NULL value is replaced by an actual value later on.

An object whose value is NULL is called atomically null. An atomically null object is different from one that simply happens to have null values for all its attributes. When all the attributes of an object are null, these attributes can still be changed, and the object's methods can be called. With an atomically null object, you can do neither of these things. In Example 2-1, consider the contacts table which contains the person_typ object type.

Example 2-1 Inserting NULLs for Objects in a Table

CREATE TYPE person_typ AS OBJECT (
  idno           NUMBER,
  name           VARCHAR2(30),
  phone          VARCHAR2(20),
  MAP MEMBER FUNCTION get_idno RETURN NUMBER, 
  MEMBER PROCEDURE display_details ( SELF IN OUT NOCOPY person_typ ) );
/

CREATE TYPE BODY person_typ AS
  MAP MEMBER FUNCTION get_idno RETURN NUMBER IS
  BEGIN
    RETURN idno;
  END;
  MEMBER PROCEDURE display_details ( SELF IN OUT NOCOPY person_typ ) IS
  BEGIN
    -- use the PUT_LINE procedure of the DBMS_OUTPUT package to display details
    DBMS_OUTPUT.PUT_LINE(TO_CHAR(idno) || ' - '  || name || ' - '  || phone);
  END;
END;
/
CREATE TABLE contacts (
  contact        person_typ,
  contact_date   DATE );

INSERT INTO contacts VALUES (
  person_typ (NULL, NULL, NULL), '24 Jun 2003' );

INSERT INTO contacts VALUES (
  NULL, '24 Jun 2003' );

The two INSERT statements give two different results. In both cases, Oracle allocates space in contacts for a new row and sets its DATE column to the value given. But in the first case, Oracle allocates space for an object in the contact column and sets each of the object's attributes to NULL. In the second case, Oracle sets the person_typ field itself to NULL and does not allocate space for an object.

In some cases, you can omit checks for null values. A table row or row object cannot be null. A nested table of objects cannot contain an element whose value is NULL.

A nested table or array can be null, so you do need to handle that condition. A null collection is different from an empty one, that is, a collection containing no elements.

Character Length Semantics

Lengths for character types CHAR and VARCHAR2 may be specified as a number of characters, instead of bytes, in object attributes and collections even if some of the characters consist of multiple bytes.

To specify character-denominated lengths for CHAR and VARCHAR2 attributes, you add a qualifier char to the length specification.

Like CHAR and VARCHAR2, NCHAR and NVARCHAR2 may also be used as attribute types in objects and collections. These types are always implicitly measured in terms of characters, so no char qualifier is used.

For example, the following statement creates an object with both a character-length VARCHAR2 attribute and an NCHAR attribute:

Example 2-2 Creating the employee_typ Object Using a char Qualifier

CREATE TYPE employee_typ AS OBJECT ( 
  name        VARCHAR2(30 char), 
  language    NCHAR(10), 
  phone       VARCHAR2(20) );
/

For CHAR and VARCHAR2 attributes whose length is specified without a char qualifier, the default unit of measure characters or bytes is determined by whether the NLS_LENGTH_SEMANTICS initialization parameter is set to CHAR or BYTE.


See Also:

Oracle Database Globalization Support Guide for information on character length semantics

Constraints for Object Tables

You can define constraints on an object table just as you can on other tables. You can define constraints on the leaf-level scalar attributes of a column object, with the exception of REFs that are not scoped.

Example 2-3 and Example 2-4 illustrate the possibilities. Example 2-3 places a PRIMARY KEY constraint on the idno column of the object table person_extent.

Example 2-3 Creating the office_tab Object Table with a Constraint

CREATE TYPE location_typ AS OBJECT (
  building_no  NUMBER,
  city         VARCHAR2(40) );
/

CREATE TYPE office_typ AS OBJECT (
  office_id    VARCHAR(10),
  office_loc   location_typ,
  occupant     person_typ );/

CREATE TABLE office_tab OF office_typ (
             office_id      PRIMARY KEY );

The department_mgrs table in Example 2-4 has a column whose type is the object type location_typ defined in Example 2-3. The example defines constraints on scalar attributes of the location_typ objects that appear in the dept_loc column of the table.

Example 2-4 Creating the department_mgrs Table with Multiple Constraints

CREATE TABLE department_mgrs (
  dept_no     NUMBER PRIMARY KEY, 
  dept_name   CHAR(20),
  dept_mgr    person_typ,
  dept_loc    location_typ,
  CONSTRAINT  dept_loc_cons1
      UNIQUE (dept_loc.building_no, dept_loc.city),
  CONSTRAINT  dept_loc_cons2
       CHECK (dept_loc.city IS NOT NULL) );

INSERT INTO department_mgrs VALUES 
          ( 101, 'Physical Sciences', 
           person_typ(65,'Vrinda Mills', '1-800-555-4412'),
           location_typ(300, 'Palo Alto'));

Indexes for Object Tables

You can define indexes on an object table or on the storage table for a nested table column or attribute just as you can on other tables. For an example of an index on a nested table, see Example 3-4.

You can define indexes on leaf-level scalar attributes of column objects, as shown in Example 2-5. You can only define indexes on REF attributes or columns if the REF is scoped. Here, dept_addr is a column object, and city is a leaf-level scalar attribute of dept_addr that we want to index.

Example 2-5 Creating an Index on an Object Type in a Table

CREATE TABLE department_loc (
  dept_no     NUMBER PRIMARY KEY, 
  dept_name   CHAR(20),
  dept_addr   location_typ );

CREATE INDEX  i_dept_addr1
          ON  department_loc (dept_addr.city);

INSERT INTO department_loc VALUES
          ( 101, 'Physical Sciences',
           location_typ(300, 'Palo Alto'));
INSERT INTO department_loc VALUES 
          ( 104, 'Life Sciences', 
           location_typ(400, 'Menlo Park'));
INSERT INTO department_loc VALUES 
          ( 103, 'Biological Sciences', 
           location_typ(500, 'Redwood Shores'));

Wherever Oracle expects a column name in an index definition, you can also specify a scalar attribute of an object column.

Triggers for Object Tables

You can define triggers on an object table just as you can on other tables. You cannot define a trigger on the storage table for a nested table column or attribute. You cannot modify LOB values in a trigger body. Otherwise, there are no special restrictions on using object types with triggers.

Example 2-6 defines a trigger on the office_tab table defined in "Constraints for Object Tables".

Example 2-6 Creating a Trigger on Objects in a Table

CREATE TABLE movement (
     idno           NUMBER,
     old_office     location_typ,
     new_office     location_typ );

CREATE TRIGGER trigger1
  BEFORE UPDATE
             OF  office_loc
             ON  office_tab
   FOR EACH ROW
           WHEN  (new.office_loc.city = 'Redwood Shores')
   BEGIN
     IF :new.office_loc.building_no = 600 THEN
      INSERT INTO movement (idno, old_office, new_office)
       VALUES (:old.occupant.idno, :old.office_loc, :new.office_loc);
     END IF;
   END;/

INSERT INTO movement VALUES 
   ( 101, location_typ(300, 'Palo Alto'),
     location_typ(400, 'Menlo Park'));

Rules for REF Columns and Attributes

In Oracle, a REF column or attribute can be unconstrained or constrained using a SCOPE clause or a referential constraint clause. When a REF column is unconstrained, it may store object references to row objects contained in any object table of the corresponding object type.

Oracle does not ensure that the object references stored in such columns point to valid and existing row objects. Therefore, REF columns may contain object references that do not point to any existing row object. Such REF values are referred to as dangling references.

A REF column may be constrained to be scoped to a specific object table. All the REF values stored in a column with a SCOPE constraint point at row objects of the table specified in the SCOPE clause. The REF values may, however, be dangling.

A REF column may be constrained with a REFERENTIAL constraint similar to the specification for foreign keys. The rules for referential constraints apply to such columns. That is, the object reference stored in these columns must point to a valid and existing row object in the specified object table.

PRIMARY KEY constraints cannot be specified for REF columns. However, you can specify NOT NULL constraints for such columns.

Name Resolution

Oracle SQL lets you omit qualifying table names in some relational operations. For example, if dept_addr is a column in the department_loc table and old_office is a column in the movement table, you can use the following:

SELECT * FROM department_loc WHERE EXISTS 
  (SELECT * FROM movement WHERE dept_addr = old_office);

Oracle determines which table each column belongs to.

Using the dot notation, you can qualify the column names with table names or table aliases to make things more maintainable. For example:

Example 2-7 Using the Dot Notation for Name Resolution

SELECT * FROM department_loc WHERE EXISTS 
  (SELECT * FROM movement WHERE department_loc.dept_addr = movement.old_office);

SELECT * FROM department_loc d WHERE EXISTS 
  (SELECT * FROM movement m WHERE d.dept_addr = m.old_office);

In some cases, object-relational features require you to specify the table aliases.

When Table Aliases Are Required

Using unqualified names can lead to problems. If you add an assignment column to depts and forget to change the query, Oracle automatically recompiles the query such that the inner SELECT uses the assignment column from the depts table. This situation is called inner capture.

To avoid inner capture and similar problems resolving references, Oracle requires you to use a table alias to qualify any dot-notational reference to methods or attributes of objects. Use of a table alias is optional when referencing top-level attributes of an object table directly, without using the dot notation.

For example, the following statements define two tables that contain the person_typ object type. person_obj_table is an object table for objects of type person_typ, and contacts is a relational table that contains a column of an object type.

The following queries show some correct and incorrect ways to reference attribute idno:


SELECT idno FROM person_obj_table; --Correct
SELECT contact.idno FROM contacts; --Illegal
SELECT contacts.contact.idno FROM contacts; --Illegal
SELECT p.contact.idno FROM contacts p; --Correct
  • In the first SELECT statement, idno is the name of a column of person_obj_table. It references this top-level attribute directly, without using the dot notation, so no table alias is required.

  • In the second SELECT statement, idno is the name of an attribute of the person_typ object in the column named contact. This reference uses the dot notation and so requires a table alias, as shown in the fourth SELECT statement.

  • The third SELECT uses the table name itself to qualify this the reference. This is incorrect; a table alias is required.

You must qualify a reference to an object attribute or method with a table alias rather than a table name even if the table name is itself qualified by a schema name.

For example, the following expression tries to refer to the HR schema, department_loc table, dept_addr column, and city attribute of that column. But the expression is incorrect because department_loc is a table name, not an alias.

HR.department_loc.dept_addr.city

The same requirement applies to attribute references that use REFs.

Table aliases should uniquely pick out the same table throughout a query and should not be the same as schema names that could legally appear in the query.


Note:

Oracle recommends that you define table aliases in all UPDATE, DELETE, and SELECT statements and subqueries and use them to qualify column references whether or not the columns contain object types.

Restriction on Using User-Defined Types with a Remote Database

User-defined types (specifically, types declared with a SQL CREATE TYPE statement, as opposed to types declared within a PL/SQL package) are currently useful only within a single database. You cannot use a database link to do any of the following:

  • Connect to a remote database to select, insert, or update a user-defined type or an object REF on a remote table

    You can use the CREATE TYPE statement with the optional keyword OID to create a user-specified object identifier (OID) that allows an object type to be used in multiple databases. See the discussion on assigning an OID to an object type in the Oracle Database Data Cartridge Developer's Guide.

  • Use database links within PL/SQL code to declare a local variable of a remote user-defined type

  • Convey a user-defined type argument or return value in a PL/SQL remote procedure call.

Object Methods

Methods are functions or procedures that you can declare in an object type definition to implement behavior that you want objects of that type to perform. An application calls the methods to invoke the behavior.

For example, you might declare a method get_sum() to get a purchase order object to return the total cost of its line items. The following line of code calls such a method for purchase order po and returns the amount into sum_line_items:

sum_line_items = po.get_sum();

In SQL, the parentheses are required for all method calls. Unlike with PL/SQL functions and procedures, SQL requires parentheses for method calls that do not have arguments.

Methods can be written in PL/SQL or virtually any other programming language. Methods written in PL/SQL or Java are stored in the database. Methods written in other languages, such as C, are stored externally.

The topics described in this section are:

Member Methods

Member methods are the means by which an application gains access to an object instance's data. You define a member method in the object type for each operation that you want an object of that type to be able to perform. For example, the method get_sum() that sums the total cost of a purchase order's line items operates on the data of a particular purchase order and is a member method.

Member methods have a built-in parameter named SELF that denotes the object instance on which the method is currently being invoked. Member methods can reference the attributes and methods of SELF without a qualifier. This makes it simpler to write member methods. In Example 2-8 the code shows a method declaration that takes advantage of SELF to omit qualification of the attributes hgt, len, and wth.

Example 2-8 Creating a Member Method

CREATE TYPE solid_typ AS OBJECT (
  len    INTEGER,
  wth    INTEGER,
  hgt    INTEGER,
  MEMBER FUNCTION surface RETURN INTEGER,
  MEMBER FUNCTION volume RETURN INTEGER,
  MEMBER PROCEDURE display (SELF IN OUT NOCOPY solid_typ) );
/

CREATE TYPE BODY solid_typ AS
  MEMBER FUNCTION volume RETURN INTEGER IS
  BEGIN
    RETURN len * wth * hgt;
 -- RETURN SELF.len * SELF.wth * SELF.hgt; -- equivalent to previous line 
  END;
  MEMBER FUNCTION surface RETURN INTEGER IS
  BEGIN -- not necessary to include SELF prefix in following line
    RETURN 2 * (len * wth + len * hgt + wth * hgt);
  END;
  MEMBER PROCEDURE display (SELF IN OUT NOCOPY solid_typ) IS
  BEGIN
    DBMS_OUTPUT.PUT_LINE('Length: ' || len || ' - '  || 'Width: ' || wth 
                          || ' - '  || 'Height: ' || hgt);
    DBMS_OUTPUT.PUT_LINE('Volume: ' || volume || ' - ' || 'Surface area: ' 
                          || surface);
  END;
END;
/

SELF does not need to be explicitly declared, although it can be. It is always the first parameter passed to the method.

  • In member functions, if SELF is not declared, its parameter mode defaults to IN.

  • In member procedures, if SELF is not declared, its parameter mode defaults to IN OUT. The default behavior does not include the NOCOPY compiler hint.

You can invoke a member method using the dot notation object_variable.method(). This notation specifies the object on which to invoke the method, then the method to call. Any parameters must be placed inside the required parentheses. See also "Using SELF IN OUT NOCOPY with Member Procedures".

Methods for Comparing Objects

The values of a scalar datatype such as CHAR or REAL have a predefined order, which allows them to be compared. But an object type, such as a person_typ, which can have multiple attributes of various datatypes, has no predefined axis of comparison. To be able to compare and order variables of an object type, you must specify a basis for comparing them. Two special kinds of member methods can be defined for doing this: map methods and order methods.

Map Methods

A map method is an optional kind of method that provides a basis for comparing objects by mapping object instances to one of the scalar types DATE, NUMBER, VARCHAR2 or to an ANSI SQL type such as CHARACTER or REAL. With a map method, you can order any number of objects by calling each object's map method once to map that object to a position on the axis used for the comparison, such as a number or date. Example 2-1 contains a simple map method.

From the standpoint of writing one, a map method is simply a parameter-less member function that uses the MAP keyword and returns one of the datatypes just listed. What makes a map method special is that, if an object type defines one, the method is called automatically to evaluate such comparisons as obj_1 > obj_2 and comparisons implied by the DISTINCT, GROUP BY, UNION, and ORDER BY clauses which require sorting by rows.

Where obj_1 and obj_2 are two object variables that can be compared using a map method map(), the comparison: 

obj_1 > obj_2

is equivalent to:

obj_1.map() > obj_2.map()

And similarly for other relational operators besides the greater than (>) operator.

The following example defines a map method area() that provides a basis for comparing rectangle objects by their area:

Example 2-9 Creating a Map Method

CREATE TYPE rectangle_typ AS OBJECT ( 
  len NUMBER,
  wid NUMBER,
  MAP MEMBER FUNCTION area RETURN NUMBER);
/

CREATE TYPE BODY rectangle_typ AS 
  MAP MEMBER FUNCTION area RETURN NUMBER IS
  BEGIN
     RETURN len * wid;
  END area;
END;
/

An object type can declare at most one map method or one order method. A subtype can declare a map method only if its root supertype declares one. See "Equal and Not Equal Comparisons" for the use of map methods when comparing collections that contain object types.

Order Methods

Order methods make direct object-to-object comparisons. Unlike map methods, they cannot map any number of objects to an external axis. They simply tell you that the current object is less than, equal to, or greater than the other object that it is being compared to, with respect to the criterion used by the method.

An order method is a function with one declared parameter for another object of the same type. The method must be written to return either a negative number, zero, or a positive number. The return signifies that the object picked out by the SELF parameter is respectively less than, equal to, or greater than the other parameter's object.

As with map methods, an order method, if one is defined, is called automatically whenever two objects of that type need to be compared.

Order methods are useful where comparison semantics may be too complex to use a map method. For example, to compare binary objects such as images, you might create an order method to compare the images by their brightness or number of pixels.

An object type can declare at most one order method or one map method. Only a type that is not derived from another type can declare an order method; a subtype cannot define one.

Example 2-10 shows an order method that compares locations by building number:

Example 2-10 Creating an Order Method

CREATE TYPE location_typ AS OBJECT (
  building_no  NUMBER,
  city         VARCHAR2(40),
  ORDER MEMBER FUNCTION match (l location_typ) RETURN INTEGER );/
CREATE TYPE BODY location_typ AS 
  ORDER MEMBER FUNCTION match (l location_typ) RETURN INTEGER IS 
  BEGIN 
    IF building_no < l.building_no THEN
      RETURN -1;               -- any negative number will do
    ELSIF building_no > l.building_no THEN 
      RETURN 1;                -- any positive number will do
    ELSE 
      RETURN 0;
    END IF;
  END;
END;/

Guidelines for Comparison Methods

A map method maps object values into scalar values and can order multiple values by their position on the scalar axis. An order method directly compares values for two particular objects.

You can declare a map method or an order method but not both. If you declare a method of either type, you can compare objects in SQL and procedural statements. However, if you declare neither method, you can compare objects only in SQL statements and only for equality or inequality. Two objects of the same type count as equal only if the values of their corresponding attributes are equal.

When sorting or merging a large number of objects, use a map method. One call maps all the objects into scalars, then sorts the scalars. An order method is less efficient because it must be called repeatedly (it can compare only two objects at a time). See "Performance of Object Comparisons".

Comparison Methods in Type Hierarchies

In a type hierarchy, where definitions of specialized types are derived from definitions of more general types, only the root type—the most basic type, from which all other types are derived—can define an order method. If the root type does not define one, its subtypes cannot define one either.

If the root type specifies a map method, any of its subtypes can define a map method that overrides the map method of the root type. But if the root type does not specify a map method, no subtype can specify one either.

So if the root type does not specify either a map or an order method, none of the subtypes can specify either a map or order method. See "Inheritance in SQL Object Types" and "Inheriting, Overloading, and Overriding Methods".

Static Methods

Static methods are invoked on the object type, not its instances. You use a static method for operations that are global to the type and do not need to reference the data of a particular object instance. A static method has no SELF parameter.

You invoke a static method by using the dot notation to qualify the method call with the name of the object type, such as:

type_name.method()

See "Static Methods" for information on design considerations.

Constructor Methods

Every object type has a constructor method implicitly defined for it by the system. A constructor method is a function that returns a new instance of the user-defined type and sets up the values of its attributes. The system implicitly defines a constructor function called the attribute value constructor for all object types that have attributes.

Consider the person_typ object type that is defined in Example 2-1. The name of the constructor method is simply the name of the object type, as shown in the following:

person_typ (1, 'John Smith', '1-800-555-1212'),

A literal invocation of a constructor method is a call to the constructor method in which any arguments are either literals, or further literal invocations of constructor methods. For example:

CREATE TABLE people_tab OF person_typ;

INSERT INTO people_tab VALUES (
       person_typ(101, 'John Smith', '1-800-555-1212') );

You can also define constructor functions of your own called user-defined constructors to create and initialize objects of such types. Attribute value constructors are convenient to use because they already exist, but user-defined constructors have some important advantages with respect to type evolution. See "Advantages of User-Defined Constructors" for information on user-defined constructors and their advantages. See "Constructor Methods for Collections" for information on user-defined constructors for collections.

External Implemented Methods

You can use PL/SQL to invoke external subprograms that have been written in other languages. This provides access to the strengths and capabilities of those languages.


See Also:

Oracle Database PL/SQL User's Guide and Reference for information on external implemented methods

Inheritance in SQL Object Types

Object types enable you to model the real-world entities such as customers and purchase orders that your application works with. But this is just the first step in exploiting the capabilities of objects. With objects, you cannot only model an entity such as a customer, you can also define different specialized types of customers in a type hierarchy under the original type. You can then perform operations on a hierarchy and have each type implement and execute the operation in a special way.

A type hierarchy is a sort of family tree of object types. It consists of a parent base type, called a supertype, and one or more levels of child object types, called subtypes, derived from the parent.

Subtypes in a hierarchy are connected to their supertypes by inheritance. This means that subtypes automatically acquire the attributes and methods of their parent type. It also means that subtypes automatically acquire any changes made to these attributes or methods in the parent: any attributes or methods updated in a supertype are updated in subtypes as well.

A subtype becomes a specialized version of the parent type by adding new attributes and methods to the set inherited from the parent or by redefining methods it inherits. Redefining an inherited methods gives a subtype its own way of executing the method. Add to this that an object instance of a subtype can generally be substituted for an object instance of any of its supertypes in code, and you have polymorphism.

Polymorphism is the ability of a slot for a value in code to contain a value of either a certain declared type or any of a range of the declared type's subtypes. A method called on whatever value occupies the slot may execute differently depending on the value's type because the various types might implement the method differently.

Types and Subtypes

A subtype can be derived from a supertype either directly, or indirectly through intervening levels of other subtypes. A subtype can directly derive only from a single supertype: it cannot derive jointly from more than one. A supertype can have multiple sibling subtypes, but a subtype can have at most one direct parent supertype. In other words, Oracle supports only single inheritance, not multiple inheritance.

A subtype is derived from a supertype by defining a specialized variant of the supertype. For example, from a person_typ object type you might derive the specialized types student_typ and employee_typ. Each of these subtypes is still at bottom a person_typ, but a special kind of person. What makes a subtype special and distinguishes it from its parent supertype is some change made in the subtype to the attributes or methods that the subtype received from its parent.

Figure 2-1 Subtypes

Description of adobj027.gif follows


An object type's attributes and methods make the type what it is: they are its essential, defining features. If a person_typ object type has the three attributes idno, name, and phone and the method get_idno(), then any object type that is derived from person_typ will have these same three attributes and a method get_idno(). A subtype is a special case of its parent type, not a totally different kind of thing. As such, it shares with its parent type the features that make the general type what it is.

You can specialize the attributes or methods of a subtype in these ways:

  • Add new attributes that its parent supertype does not have.

    For example, you might specialize student_typ as a special kind of person_typ by adding to its definition an attribute for major. A subtype cannot drop or change the type of an attribute it inherited from its parent; it can only add new attributes.

  • Add entirely new methods that the parent does not have.

  • Change the implementation of some of the methods a subtype inherits from its parent so that the subtype's version executes different code from the parent's.

    For example, a shape object type might define a method calculate_area(). Two subtypes of shape, rectilinear_shape, and circular_shape, might each implement this method in a different way. See "Inheriting, Overloading, and Overriding Methods".

Attributes and methods that a subtype gets from its parent type are said to be inherited. This means more than just that the attributes and methods are patterned on the parent's when the subtype is defined. With object types, the inheritance link remains live. Any changes made later on to the parent type's attributes or methods are also inherited so that the changes are reflected in the subtype as well. Unless a subtype reimplements an inherited method, it always contains the same core set of attributes and methods that are in the parent type, plus any attributes and methods that it adds.

Remember, a child type is not a different type from its parent; it is a particular kind of that type. If the general definition of person_typ ever changes, the definition of student_typ changes also.

The inheritance relationship that holds between a supertype and its subtypes is the source of both much of the power of objects and much of their complexity. It is a very powerful feature to be able to change a method in a supertype and have the change take effect in all the subtypes downstream just by recompiling. But this same capability means that you have to think about such things as whether you want to allow a type to be specialized or a method to be redefined. Similarly, it is a powerful feature for a table or column to be able to contain any type in a hierarchy, but then you must decide whether to allow this in a particular case, and you may need to constrain DML statements and queries so that they pick out from the type hierarchy just the range of types that you want. The following sections address these aspects of working with objects.

FINAL and NOT FINAL Types and Methods

The definition of an object type determines whether subtypes can be derived from that type. To permit subtypes, the object type must be defined as not final. This is done by including the NOT FINAL keyword in its type declaration, as shown in Example 2-11.

Example 2-11 Creating the person_typ Object Type as NOT FINAL

CREATE TYPE person_typ AS OBJECT (
   idno           NUMBER,
   name           VARCHAR2(30),
   phone          VARCHAR2(20)) 
NOT FINAL;
/

The preceding statement declares person_typ to be a not final type such that subtypes of person_typ can be defined. By default, an object type is declared as final and subtypes cannot be derived from it.

You can change a final type to a not final type and vice versa with an ALTER TYPE statement. For example, the following statement changes person_typ to a final type:

ALTER TYPE person_typ FINAL;

You can alter a type from NOT FINAL to FINAL only if the target type has no subtypes.

Methods can also be declared to be final or not final. If a method is declared to be final, subtypes cannot override it by providing their own implementation. Unlike types, methods are not final by default and must be explicitly declared to be final.

Example 2-12 creates a not final type containing a final member function.

Example 2-12 Creating an Object Type as NOT FINAL with a FINAL Member Function

CREATE TYPE person_typ AS OBJECT (
   idno           NUMBER,
   name           VARCHAR2(30),
   phone          VARCHAR2(20),
   FINAL MAP MEMBER FUNCTION get_idno RETURN NUMBER)
NOT FINAL;
/

See "Redefining Methods".

Creating Subtypes With Overriding Methods

You can create a subtype using a CREATE TYPE statement that specifies the immediate parent of the subtype with an UNDER clause. Example 2-13 shows the creation of the parent or supertype person_typ object; Example 2-14, Example 2-15, and Example 2-16 show the definition of the subtypes.

Note the methods that are created in the supertype body of Example 2-13. In Example 2-14, Example 2-15, and Example 2-16, the show() function of the parent type is overridden to specifications for each subtype. At the same time, the static show_super() function is designed so that it can be called as it is in the supertype from every subtype under the person_typ parent object.

Example 2-13 Creating the Parent or Supertype person_typ Object

CREATE TYPE person_typ AS OBJECT (
  idno           NUMBER,
  name           VARCHAR2(30),
  phone          VARCHAR2(20),
  MAP MEMBER FUNCTION get_idno RETURN NUMBER,
  STATIC FUNCTION show_super (person_obj in person_typ) RETURN VARCHAR2,
  MEMBER FUNCTION show RETURN VARCHAR2)
  NOT FINAL;
/

CREATE TYPE BODY person_typ AS
  MAP MEMBER FUNCTION get_idno RETURN NUMBER IS
  BEGIN
    RETURN idno;
  END;

-- static function that can be called by subtypes
 STATIC FUNCTION show_super (person_obj in person_typ) RETURN VARCHAR2 IS
  BEGIN
    RETURN 'Id: ' || TO_CHAR(person_obj.idno) || ', Name: ' || person_obj.name;
  END;

-- function that can be overriden by subtypes 
  MEMBER FUNCTION show RETURN VARCHAR2 IS
  BEGIN
    RETURN person_typ.show_super ( SELF );
  END; 

END;
/

Example 2-14 creates student_typ as a subtype of person_typ. As a subtype of person_typ, student_typ inherits all the attributes declared in or inherited by person_typ and any methods inherited by person_typ or declared in person_typ.

The statement that defines student_typ specializes person_typ by adding two new attributes. In addition, the show() function is overridden to display the new attribute major. New attributes declared in a subtype must have names that are different from the names of any attributes or methods declared in any of its supertypes, higher up in its type hierarchy.

Example 2-14 Creating a student_typ Subtype Using the UNDER Clause

CREATE TYPE student_typ UNDER person_typ (
    dept_id NUMBER,
    major VARCHAR2(30),
    OVERRIDING MEMBER FUNCTION show RETURN VARCHAR2)
    NOT FINAL;
/

CREATE TYPE BODY student_typ AS
  OVERRIDING MEMBER FUNCTION show RETURN VARCHAR2 IS
  BEGIN
    RETURN person_typ.show_super ( SELF ) || ' -- Major: ' || major ;
  END;
  
END;
/

A type can have multiple child subtypes, and these can also have subtypes. Example 2-15 creates another subtype employee_typ under person_typ.

Example 2-15 Creating an employee_typ Subtype Using the UNDER Clause

CREATE TYPE employee_typ UNDER person_typ (
    emp_id NUMBER, 
    mgr VARCHAR2(30),
    OVERRIDING MEMBER FUNCTION show RETURN VARCHAR2);
/

CREATE TYPE BODY employee_typ AS
  OVERRIDING MEMBER FUNCTION show RETURN VARCHAR2 IS
  BEGIN
    RETURN person_typ.show_super ( SELF ) || ' -- Employee Id: ' 
           || TO_CHAR(emp_id) || ', Manager: ' || mgr ;
  END;
  
END;
/

A subtype can be defined under another subtype. Again, the new subtype inherits all the attributes and methods that its parent type has, both declared and inherited. Example 2-16 defines a new subtype part_time_student_typ under student_typ. The new subtype inherits all the attributes and methods of student_typ and adds another attribute.

Example 2-16 Creating a part_time_student_typ Subtype Using the UNDER Clause

CREATE TYPE part_time_student_typ UNDER student_typ (
  number_hours NUMBER,
  OVERRIDING MEMBER FUNCTION show RETURN VARCHAR2);
/

CREATE TYPE BODY part_time_student_typ AS
  OVERRIDING MEMBER FUNCTION show RETURN VARCHAR2 IS
  BEGIN
    RETURN person_typ.show_super ( SELF ) || ' -- Major: ' || major ||
           ', Hours: ' || TO_CHAR(number_hours);
  END;
  
END;
/

You can create a table that contains the supertype and subtypes and populate the table as shown with the person_obj_table in Example 2-17.

Example 2-17 Inserting Values into Substitutable Rows of an Object Table

CREATE TABLE person_obj_table OF person_typ;

INSERT INTO person_obj_table 
  VALUES (person_typ(12, 'Bob Jones', '111-555-1212'));

INSERT INTO person_obj_table 
  VALUES (student_typ(51, 'Joe Lane', '1-800-555-1312', 12, 'HISTORY'));

INSERT INTO person_obj_table 
  VALUES (employee_typ(55, 'Jane Smith', '1-800-555-7765', 
                       100, 'Jennifer Nelson'));

INSERT INTO person_obj_table  
  VALUES (part_time_student_typ(52, 'Kim Patel', '1-800-555-1232', 14,
         'PHYSICS', 20));

You can call the show() function for the supertype and subtypes in the table with the following:

SELECT p.show() FROM person_obj_table p;

With the table populated as illustrated in Example 2-17, the output is similar to:


Id: 12, Name: Bob Jones
Id: 51, Name: Joe Lane -- Major: HISTORY
Id: 55, Name: Jane Smith -- Employee Id: 100, Manager: Jennifer Nelson
Id: 52, Name: Kim Patel -- Major: PHYSICS, Hours: 20

Note the overridden show() function displays an output specific to the supertype or subtype while the results of the static show_super() are constant.

NOT INSTANTIABLE Types and Methods

A type can be declared to be NOT INSTANTIABLE. If a type is not instantiable, there is no constructor (default or user-defined) for it, and you cannot instantiate instances of that type (objects, in other words). You might use this option with types that you intend to use solely as supertypes of specialized subtypes that you do instantiate. The following pseudocode provides an example.


CREATE TYPE address_typ AS OBJECT(...)
    NOT INSTANTIABLE NOT FINAL;
CREATE TYPE USaddress_typ UNDER address_typ(...);
CREATE TYPE Intladdress_typ UNDER address_typ(...);

A method can also be declared to be not instantiable. Use this option when you want to declare a method in a type without implementing the method there. A type that contains a non-instantiable method must itself be declared not instantiable, as shown in Example 2-18.

Example 2-18 Creating an Object Type that is NOT INSTANTIABLE

CREATE TYPE person_typ AS OBJECT (
  idno           NUMBER,
  name           VARCHAR2(30),
  phone          VARCHAR2(20),
  NOT INSTANTIABLE MEMBER FUNCTION get_idno RETURN NUMBER)
  NOT INSTANTIABLE NOT FINAL;/

A non-instantiable method serves as a placeholder. You might define a non-instantiable method when you expect every subtype to override the method in a different way. In such a case, there is no point in defining the method in the supertype.

If a subtype does not provide an implementation for every inherited non-instantiable method, the subtype itself, like the supertype, must be declared not instantiable. A non-instantiable subtype can be defined under an instantiable supertype.

You can alter an instantiable type to a non-instantiable type and vice versa with an ALTER TYPE statement. In the following example, the ALTER TYPE statement makes person_typ instantiable:

Example 2-19 Altering an Object Type to INSTANTIABLE

CREATE TYPE person_typ AS OBJECT (
  idno           NUMBER,
  name           VARCHAR2(30),
  phone          VARCHAR2(20))
  NOT INSTANTIABLE NOT FINAL;/
ALTER TYPE person_typ INSTANTIABLE;

You can alter an instantiable type to a non-instantiable type only if the type has no columns, views, tables, or instances that reference that type, either directly, or indirectly through another type or subtype.

You cannot declare a non-instantiable type to be FINAL, which would be pointless anyway.

Inheriting, Overloading, and Overriding Methods

A subtype automatically inherits all methods (both member and static methods) declared in or inherited by its supertype.

A subtype can redefine methods it inherits, and it can also add new methods. It can even add new methods that have the same names as methods it inherits, such that the subtype ends up containing more than one method with the same name.

Giving a type multiple methods with the same name is called method overloading. Redefining an inherited method to customize its behavior in a subtype is either overriding, in the case of member methods, or hiding, in the case of static methods.

See the examples in "Creating Subtypes With Overriding Methods" and Example 7-7.

Overloading Methods

Overloading is useful when you want to provide a variety of ways of doing something. For example, a shape object might overload a draw() method with another draw() method that adds a text label to the drawing and contains an argument for the label's text.

When a type has several methods with the same name, the compiler uses the methods' signatures to tell them apart. A method's signature is a sort of structural profile. It consists of the method's name and the number, types, and order of the method's formal parameters, including the implicit self parameter. Methods that have the same name, but different signatures are called overloads when they exist in the same user-defined type.

In the following pseudocode, Subtype MySubType_typ creates an overload of draw():


CREATE TYPE MyType_typ AS OBJECT (...,
  MEMBER PROCEDURE draw(x NUMBER), ...) NOT FINAL;

CREATE TYPE MySubType_typ UNDER MyType_typ (...,
  MEMBER PROCEDURE draw(x VARCHAR2(20)),
  STATIC FUNCTION bar(...)...
  ...);

MySubType_typ contains two versions of draw(). One is an inherited version with a NUMBER parameter and the other has a VARCHAR2 parameter.

Redefining Methods

Overriding and hiding redefine an inherited method to make it do something different in the subtype. For example, a subtype circular_shape derived from a shape supertype might override a member method calculate_area() to customize it specifically for calculating the area of a circle. For examples of overriding methods, see "Creating Subtypes With Overriding Methods".

Redefining a method is called overriding when the method that is redefined is a member method; redefining is called hiding when the redefined method is a static method. Overriding and hiding are similar in that, in either case, the version of the method redefined in the subtype eclipses an inherited version of the same name and signature such that the new version is executed instead of the inherited one whenever an instance of the subtype invokes the method. If the subtype itself has subtypes, these inherit the redefined method instead of the original version.

However, with overriding, the system relies on type information contained in the member method's implicit self argument to dynamically choose the correct version of the method to execute. With hiding, the correct version can be identified at compile time, and dynamic dispatch is not necessary. See "Dynamic Method Dispatch".

It is possible that a supertype may contain overloads of a method that is redefined in a subtype. Overloads of a method all have the same name, so the compiler uses the signature of the subtype's method to identify the particular version in the supertype that is superseded. This means that, to override or hide a method, you must preserve its signature.

A subtype that overrides a member method must signal the override with the OVERRIDING keyword in the type definition. No such special keyword is required when a subtype hides a static method.

For example, in the following pseudocode, the subtype signals that it is overriding method Print():


CREATE TYPE MyType_typ AS OBJECT (...,
  MEMBER PROCEDURE Print(),
  FINAL MEMBER FUNCTION function_mytype(x NUMBER)...
) NOT FINAL;

CREATE TYPE MySubType_typ UNDER MyType_typ (...,
  OVERRIDING MEMBER PROCEDURE Print(),
...);

As with new methods, you supply the declaration for a method that hides or overrides in a CREATE TYPE BODY statement.

Restrictions on Overriding Methods

The following are restrictions on overriding methods:

  • You can override only methods that are not declared to be final in the supertype.

  • Order methods may appear only in the root type of a type hierarchy: they may not be redefined (overridden) in subtypes.

  • A static method in a subtype may not redefine a member method in the supertype.

  • A member method in a subtype may not redefine a static method in the supertype.

  • If a method being overridden provides default values for any parameters, then the overriding method must provide the same default values for the same parameters.

  • When implementing methods using PL/SQL, you cannot call a supertype object method with the super keyword or an equivalent method in derived objects that have overriding methods. However, you can call a static supertype method as a workaround. See the examples in "Creating Subtypes With Overriding Methods" for the definition of the supertype and subtype functions.

Dynamic Method Dispatch

As a result of method overriding, a type hierarchy can define multiple implementations of the same method. For example, in a hierarchy of the types ellipse_typ, circle_typ, sphere_typ, each type might define a method calculate_area() differently.

Figure 2-2 Hierarchy of Types

Description of adobj025.gif follows


When such a method is invoked, the type of the object instance that invokes it is used to determine which implementation of the method to use. The call is then dispatched to that implementation for execution. This process of selecting a method implementation is called virtual or dynamic method dispatch because it is done at run time, not at compile time.

A method call is dispatched to the nearest implementation, working back up the inheritance hierarchy from the current or specified type. If the call invokes a member method of an object instance, the type of that instance is the current type, and the implementation defined or inherited by that type is used. If the call invokes a static method of a type, the implementation defined or inherited by that specified type is used.

For example, if c1 is an object instance of circle_typ, c1.proc() looks first for an implementation of proc() defined in circle_typ. If none is found, it looks up the supertype chain for an implementation in ellipse_typ. The fact that sphere_typ also defines an implementation is irrelevant because the type hierarchy is searched only upwards, toward the top. Subtypes of the current type are not searched.

Similarly, a call to a static method circle_typ.bar() looks first in circle_typ and then, if necessary, in the supertype(s) of circle_typ. The subtype sphere_typ is not searched.


See Also:

Oracle Database PL/SQL User's Guide and Reference for information on how subprograms calls are resolved and the dynamic dispatch feature

Substituting Types in a Type Hierarchy

In a type hierarchy, the subtypes are variant kinds of the root, base type. For example, a student_typ type and an employee_typ are kinds of a person_typ. The base type includes these other types.

When you work with types in a type hierarchy, sometimes you want to work at the most general level and, for example, select or update all persons. But sometimes you want to select or update only students, or only persons who are not students.

The (polymorphic) ability to select all persons and get back not only objects whose declared type is person_typ but also objects whose declared subtype is student_typ or employee_typ is called substitutability. A supertype is substitutable if one of its subtypes can substitute or stand in for it in a slot (a variable, column, and so forth) whose declared type is the supertype.

In general, types are substitutable. Object attributes, collection elements and REFs are substitutable. An attribute defined as a REF, type, or collection of type person_typ can hold a REF to, an instance of, or instances of an instance of person_typ or an instance of any subtype of person_typ.

This is what you would expect, given that a subtype is, after all, just a specialized kind of any of its supertypes. Formally, though, a subtype is a type in its own right: it is not the same type as its supertype. A column that holds all persons, including all persons who are students and all persons who are employees, actually holds data of multiple types.

Substitutability comes into play in attributes, columns, and rows (namely, of an object view or object table) declared to be an object type, a REF to an object type, or a collection type.

In principle, object attributes, collection elements and REFs are always substitutable: there is no syntax at the level of the type definition to constrain their substitutability to some subtype. You can, however, turn off or constrain substitutability at the storage level, for specific tables and columns. See "Turning Off Substitutability in a New Table" and "Constraining Substitutability".

Column and Row Substitutability

Object type columns are substitutable, and so are object-type rows in object tables and views. In other words, a column or row defined to be of type t can contain instances of t and any of its subtypes.

For example, consider the person_typ type hierarchy introduced in "Creating Subtypes With Overriding Methods". An object table of person_typ can contain rows of all three types. You insert an instance of a given type using the constructor for that type in the VALUES clause of the INSERT statement as shown in Example 2-17.

Similarly, in a relational table or view, a substitutable column of type person_typ can contain instances of all three types. The following example inserts a person, a student, and a part-time student in the person_typ column contact:

Example 2-20 Inserting Values into Substitutable Columns of a Table

CREATE TABLE contacts (
  contact         person_typ,
  contact_date    DATE );

INSERT INTO contacts 
  VALUES (person_typ (12, 'Bob Jones', '111-555-1212'), '24 Jun 2003' );

INSERT INTO contacts 
  VALUES (student_typ(51, 'Joe Lane', '1-800-555-1312', 12, 'HISTORY'),
         '24 Jun 2003' );

INSERT INTO contacts 
  VALUES (part_time_student_typ(52, 'Kim Patel', '1-800-555-1232', 14,
          'PHYSICS', 20), '24 Jun 2003' );

A newly created subtype can be stored in any substitutable tables and columns of its supertype, including tables and columns that existed before the subtype was created.

Attributes in general can be accessed using the dot notation. Attributes of a subtype of a row or column's declared type can be accessed with the TREAT function. For example:

SELECT TREAT(contact AS student_typ).major FROM contacts;

See "TREAT".

Using OBJECT_VALUE and OBJECT_ID with Substitutable Rows

The OBJECT_VALUE and OBJECT_ID pseudocolumns allow you to access and identify the value and OID of a substitutable row in an object table as shown in Example 2-21.

Example 2-21 Using OBJECT_VALUE and OBJECT_ID

CREATE TABLE person_obj_table OF person_typ;

INSERT INTO person_obj_table
  VALUES (person_typ(20, 'Bob Jones', '111-555-1212'));

SELECT p.object_id, p.object_value FROM person_obj_table p;

Subtypes Having Supertype Attributes

A subtype can have an attribute that is a supertype. For example:

Example 2-22 Creating a Subtype with a Supertype Attribute

CREATE TYPE student_typ UNDER person_typ (
    dept_id   NUMBER,
    major     VARCHAR2(30),
    advisor   person_typ);
/

However, columns of such types are not substitutable. Similarly, a subtype ST can have a collection attribute whose element type is one of ST's supertypes, but, again, columns of such types are not substitutable. For example, if student_typ had a nested table or varray of person_typ, the student_typ column would not be substitutable.

You can, however, define substitutable columns of subtypes that have REF attributes that reference supertypes. For example, the composite_category_typ subtype shown in Example 2-21 contains the subcategory_ref_list nested table. This table contains subcategory_ref_list_typ which are REFs to category_typ. The subtype was created as follows:


CREATE TYPE subcategory_ref_list_typ
  AS TABLE OF REF category_typ;
/

CREATE TYPE composite_category_typ
  UNDER category_typ
    (
      subcategory_ref_list subcategory_ref_list_typ
...

See "Turning Off Substitutability in a New Table".

REF Columns and Attributes

REF columns and attributes are substitutable in both views and tables. For example, in either a view or a table, a column declared to be REF person_typ can hold references to instances of person_typ or any of its subtypes.

Collection Elements

Collection elements are substitutable in both views and tables. For example, a nested table of person_typ can contain object instances of person_typ or any of its subtypes.

Creating Subtypes After Creating Substitutable Columns

If you create a subtype, any table that already has substitutable columns of the supertype is automatically enabled to store the new subtype as well. This means that your options for creating subtypes are affected by the existence of such tables. If such a table exists, you can only create subtypes that are substitutable, that is, subtypes that Oracle can enable that table to store.

The following example shows an attempt to create a subtype student_typ under person_typ.

Example 2-23 Creating a Subtype After Creating Substitutable Columns

CREATE TYPE person_typ AS OBJECT (
  idno           NUMBER,
  name           VARCHAR2(30),
  phone          VARCHAR2(20))
  NOT FINAL;/

CREATE TYPE employee_typ UNDER person_typ (
    emp_id NUMBER, 
    mgr VARCHAR2(30));
/

CREATE TABLE person_obj_table (p person_typ);

The following statement fails because student_typ has a supertype attribute, and table person_obj_table has a substitutable column p of the supertype.

CREATE TYPE student_typ UNDER person_typ ( -- incorrect CREATE subtype
    advisor person_typ);
/

The following attempt succeeds. This version of the student_typ subtype is substitutable. Oracle automatically enables table person_obj_table to store instances of this new type.

CREATE TYPE student_typ UNDER person_typ (
    dept_id NUMBER,
    major VARCHAR2(30));/
INSERT INTO person_obj_table 
  VALUES (student_typ(51, 'Joe Lane', '1-800-555-1312', 12, 'HISTORY'));

Dropping Subtypes After Creating Substitutable Columns

You can drop a subtype with the VALIDATE option only if no instances of the subtype are stored in any substitutable column of the supertype.

For example, the following statement fails because an instance of student_typ is stored in substitutable column p of table person_obj_table:

DROP TYPE student_typ VALIDATE -- incorrect DROP TYPE ; 

To drop the type, first delete any of its instances in substitutable columns of the supertype:

DELETE FROM person_obj_table WHERE p IS OF (student_typ); 

DROP TYPE student_typ VALIDATE;

Turning Off Substitutability in a New Table

When creating a table, you can turn off all substitutability on a column or attribute, including embedded attributes and collections nested to any level, with the clause NOT SUBSTITUTABLE AT ALL LEVELS.

In the following example, the clause confines column office of a relational table to storing only office_typ instances and disallows any subtype instances:

Example 2-24 Turning off Substitutability When Creating a Table

CREATE TYPE office_typ AS OBJECT ( office_id VARCHAR(10), location location_typ, occupant person_typ ) NOT FINAL;/ CREATE TABLE dept_office ( dept_no NUMBER, office office_typ) COLUMN office NOT SUBSTITUTABLE AT ALL LEVELS;

With object tables, the clause can be applied to the table as a whole, like this:

CREATE TABLE office_tab OF office_typ
  NOT SUBSTITUTABLE AT ALL LEVELS;

Alternatively, the clause can also be applied to turn off substitutability in a particular column that is, for a particular attribute of the object type of the table:

CREATE TABLE office_tab OF office_typ
  COLUMN occupant NOT SUBSTITUTABLE AT ALL LEVELS;

You can specify that the element type of a collection is not substitutable using syntax like the following:

CREATE TABLE people_tab (
    people_column people_typ )
    NESTED TABLE people_column 
      NOT SUBSTITUTABLE AT ALL LEVELS STORE AS people_column_nt;

There is no mechanism to turn off substitutability for REF columns.

Constraining Substitutability

You can impose a constraint that limits the range of subtypes permitted in an object column or attribute to a particular subtype in the declared type's hierarchy. You do this using an IS OF type constraint.

For example, the following statement creates a table of office_typ in which occupants are constrained to just those persons who are employees:

Example 2-25 Constraining Substitutability When Creating a Table

CREATE TABLE office_tab OF office_typ
  COLUMN occupant IS OF (ONLY employee_typ);

Although the type office_typ allows authors to be of type person_typ, the column declaration imposes a constraint to store only instances of employee_typ.

You can only use the IS OF type operator to constrain row and column objects to a single subtype (not several), and you must use the ONLY keyword, as in the preceding example.

You can use either IS OF type or NOT SUBSTITUTABLE AT ALL LEVELS to constrain an object column, but you cannot use both.

Modifying Substitutability

In an existing table, you can change an object column from SUBSTITUTABLE to NOT SUBSTITUTABLE (or from NOT SUBSTITUTABLE to SUBSTITUTABLE) by using an ALTER TABLE statement. To do so, you specify the clause [NOT] SUBSTITUTABLE AT ALL LEVELS for the particular column.

You can modify substitutability only for a specific column; you cannot modify substitutability for an object table as a whole.

The following statement makes column office substitutable:

Example 2-26 Modifying Substitutability in a Table

ALTER TABLE dept_office
  MODIFY COLUMN office SUBSTITUTABLE AT ALL LEVELS;  

The following statement makes the column not substitutable. Notice that it also uses the FORCE keyword. This keyword causes any hidden columns containing typeid information or data for subtype attributes to be dropped:

ALTER TABLE  dept_office
  MODIFY COLUMN office NOT SUBSTITUTABLE AT ALL LEVELS FORCE;

If the FORCE keyword is not used when a column is made not substitutable, the column and all attributes of the type must be FINAL or the ALTER TABLE statement will fail.

A VARRAY column can be modified from SUBSTITUTABLE to NOT SUBSTITUTABLE only if the element type of the varray is final itself and has no embedded types (in its attributes or in their attributes, and so on) that are not final.

See "Hidden Columns for Substitutable Columns and Tables" for more information about hidden columns for typeids and subtype attributes.

Restrictions on Modifying Substitutability

You can change the substitutability of only one column at a time with an ALTER TABLE statement. To change substitutability for multiple columns, you must issue multiple statements.

In an object table, you can modify substitutability for a column only if substitutability was not explicitly set at the table level, for the entire table, when the table was created.

For example, the following attempt to modify substitutability for column address succeeds because substitutability has not been explicitly turned on or off at the table level in the CREATE TABLE statement:

CREATE TABLE office_tab OF office_typ;

ALTER TABLE office_tab
  MODIFY COLUMN occupant NOT SUBSTITUTABLE AT ALL LEVELS FORCE;

However, in the following example, substitutability is explicitly set at the table level, so the attempt to modify the setting for column address fails:

CREATE TABLE office_tab OF office_typ
  NOT SUBSTITUTABLE AT ALL LEVELS;

/* Following SQL statement generates an error: */
ALTER TABLE office_tab 
  MODIFY COLUMN occupant SUBSTITUTABLE AT ALL LEVELS FORCE  -- incorrect ALTER;

A column whose substitutability is already constrained by an IS OF type operator cannot have its substitutability modified with a [NOT] SUBSTITUTABLE AT ALL LEVELS clause. See "Constraining Substitutability" for information about IS OF type.

Assignments Across Types

The assignment rules described in this section apply to INSERT/UPDATE statements, the RETURNING clause, function parameters, and PL/SQL variables.

Objects and REFs to Objects

Substitutability is the ability of a subtype to stand in for one of its supertypes. An attempt to perform a substitution in the other direction, to substitute a supertype for a subtype, raises an error at compile time.

An assignment of a source of type source_typ to a target of type target_typ must be of one of the following two patterns:

  • Case 1: source_typ and target_typ are the same type

  • Case 2: source_typ is a subtype of target_typ (widening)

Case 2 illustrates widening. Widening is an assignment in which the declared type of the source is more specific than the declared type of the target. For example, assigning an employee instance to a variable of person type.

Intuitively, the idea here is that you are regarding an employee as a person. An employee is a more narrowly defined, specialized kind of person, so you can put an employee in a slot meant for a person if you do not mind ignoring whatever extra specialization makes that person an employee. All employees are persons, so a widening assignment always works.

To illustrate widening, suppose that you have the following table:


TABLE T(pers_col person_typ, emp_col employee_typ,
        stu_col student_typ)

The following assignments show widening. The assignments are valid unless perscol has been defined to be not substitutable.

UPDATE T set pers_col = emp_col;

The following is a PL/SQL example:

DECLARE
  var1 person_typ;
  var2 employee_typ;
BEGIN
  var2 := employee_typ(55, 'Jane Smith', '1-800-555-7765', 100, 'Jennifer Nelson');
  var1 := var2;
END;
/

Besides widening, there is also narrowing. Narrowing is the reverse of widening. It involves regarding a more general, less specialized type of thing, such as a person, as a more narrowly defined type of thing, such as an employee. Not all persons are employees, so a particular assignment like this works only if the person in question actually happens to be an employee.

To do a narrowing assignment, you must use the TREAT function to test that the source instance of the more general declared type is in fact an instance of the more specialized target typIfe and can therefore be operated on as such. The TREAT function does a runtime check to confirm this and returns NULL if the source value the person in question is not of the target type or one of its subtypes.

For example, the following UPDATE statement sets values of person_typ in column perscol into column empcol of employee_typ. For each value in perscol, the assignment succeeds only if that person is also an employee. If person George is not an employee, TREAT returns NULL, and the assignment returns NULL.

UPDATE T set emp_col = TREAT(pers_col AS employee_typ);

The following statement attempts to do a narrowing assignment without explicitly changing the declared type of the source value. The statement will return an error:

UPDATE T set emp_col = pers_col;

See "TREAT".

Collection Assignments

In assignments of expressions of a collection type, the source and target must be of the same declared type. Neither widening nor narrowing is permitted. However, a subtype value can be assigned to a supertype collection. For example, suppose we have the following collection types:

CREATE TYPE person_set AS TABLE OF person_typ;
/

CREATE TYPE student_set AS TABLE OF student_typ;
/

Expressions of these different collection types cannot be assigned to each other, but a collection element of student_typ can be assigned to a collection of PersonSet type:

DECLARE
  var1 person_set; 
  var2 student_set;
  elem1 person_typ; 
  elem2 student_typ;
BEGIN
--  var1 := var2;   /* ILLEGAL - collections not of same type */
  var1 := person_set (elem1, elem2);   /* LEGAL : Element is of subtype */
END;
/

Comparisons of Objects, REF Variables, and Collections

This section discusses the comparison operators used in SQL conditions.


See Also:

Oracle Database SQL Reference for information about using SQL conditions

Comparing Object Instances

Two object instances can be compared if, and only if, they are both of the same declared type, or one is a subtype of the other.

Map methods and order methods provide the mechanism for comparing objects. You optionally define one or the other of these in an object type to specify the basis on which you want objects of that type to be compared. If a method of either sort is defined, it is called automatically whenever objects of that type or one of its subtypes need to be compared.

If a type does not define either a map method or an order method, object variables of that type can be compared only in SQL statements and only for equality or inequality. Two objects of the same type count as equal only if the values of their corresponding attributes are equal. See "Methods for Comparing Objects".

Comparing REF Variables

Two REF variables can be compared if, and only if, the targets that they reference are both of the same declared type, or one is a subtype of the other.

Functions and Operators Useful with Objects

Several functions and operators are particularly useful for working with objects and references to objects:

Examples are given throughout this book.

In PL/SQL the VALUE, REF and DEREF functions can appear only in a SQL statement. For information about SQL functions, see Oracle Database SQL Reference.

CAST

CAST converts one built-in datatype or collection-typed value into another built-in datatype or collection-typed value. For example:

Example 2-27 Using the CAST Function

CREATE TYPE person_list_typ AS TABLE OF person_typ;/

SELECT CAST(COLLECT(contact) AS person_list_typ) 
  FROM contacts;

For more information about the SQL CAST function, see Oracle Database SQL Reference.

CURSOR

A CURSOR expression returns a nested cursor. This form of expression is equivalent to the PL/SQL REF CURSOR and can be passed as a REF CURSOR argument to a function.

For more information about the SQL CURSOR expression, see Oracle Database SQL Reference.

DEREF

The DEREF function in a SQL statement returns the object instance corresponding to a REF. The object instance returned by DEREF may be of the declared type of the REF or any of its subtypes.

For example, the following statement returns person_typ objects from the table contact_ref.

Example 2-28 Using the DEREF Function

SELECT DEREF(c.contact_ref), c.contact_date 
  FROM contacts_ref c;

See "Dereferencing REFs". For more information about the SQL DEREF function, see Oracle Database SQL Reference.

IS OF type

The IS OF type predicate tests object instances for the level of specialization of their type.

For example, the following query retrieves all student instances (including any subtypes of students) stored in the person_obj_table table.

Example 2-29 Using the IS OF type Operator to Query Value of a Subtype

SELECT VALUE(p) 
  FROM person_obj_table p
WHERE VALUE(p) IS OF (student_typ);

For any object that is not of a specified subtype, or a subtype of a specified subtype, IS OF returns FALSE. Subtypes of a specified subtype are just more specialized versions of the specified subtype. If you want to exclude such subtypes, you can use the ONLY keyword. This keyword causes IS OF to return FALSE for all types except the specified types.

In the following example, the statement tests objects in object table person_obj_table, which contains persons, employees, and students, and returns REFs just to objects of the two specified person subtypes employee_typ, student_typ, and their subtypes, if any:

SELECT REF(p) 
  FROM person_obj_table p
WHERE VALUE(p) IS OF (employee_typ, student_typ);

Here is a similar example in PL/SQL. The code does something if the person is an employee or student:

DECLARE 
  var person_typ; 
BEGIN 
  var := employee_typ(55, 'Jane Smith', '1-800-555-7765', 100, 'Jennifer Nelson');
  IF var IS OF (employee_typ, student_typ) THEN 
     DBMS_OUTPUT.PUT_LINE('Var is an employee_typ or student_typ object.');
  ELSE
     DBMS_OUTPUT.PUT_LINE('Var is not an employee_typ or student_typ object.');
  END IF;
END;
/

The following statement returns only students whose most specific or specialized type is student_typ. If the table or view contains any objects of a subtype of student_typ, such as part_time_student_typ, these are excluded. The example uses the TREAT function to convert objects that are students to student_typ from the declared type of the view, person_typ:

SELECT TREAT(VALUE(p) AS student_typ)
  FROM person_obj_table p 
WHERE VALUE(p) IS OF(ONLY student_typ);

To test the type of the object that a REF points to, you can use the DEREF function to dereference the REF before testing with the IS OF type predicate.

For example, if contact_ref is declared to be REF person_typ, you can get just the rows for students as follows:

SELECT * 
  FROM contacts_ref
WHERE DEREF(contact_ref) IS OF (student_typ);

For more information about the SQL IS OF type condition, see Oracle Database SQL Reference.

REF

The REF function in a SQL statement takes as an argument a correlation name for an object table or view and returns a reference (a REF) to an object instance from that table or view. The REF function may return references to objects of the declared type of the table, view, or any of its subtypes. For example, the following statement returns the references to all persons, including references to students and employees, whose idno attribute is 12:

Example 2-30 Using the REF Function

SELECT REF(p) 
  FROM person_obj_table p
  WHERE p.idno = 12;

For more information about the SQL REF function, see Oracle Database SQL Reference.

SYS_TYPEID

The SYS_TYPEID function can be used in a query to return the typeid of the most specific type of the object instance passed to the function as an argument.

The most specific type of an object instance is the type to which the instance belongs that is farthest removed from the root type. For example, if Tim is a part-time student, he is also a student and a person, but his most specific type is part-time student.

The function returns the typeids from the hidden type discriminant column that is associated with every substitutable column. The function returns a null typeid for a final, root type.

The syntax of the function is:

SYS_TYPEID(object_type_value)

Function SYS_TYPEID may be used only with arguments of an object type. Its primary purpose is to make it possible to build an index on a hidden type discriminant column.

All types that do belong to a type hierarchy are assigned a non-null typeid that is unique within the type hierarchy. Types that do not belong to a type hierarchy have a null typeid.

Every type except a final root type belongs to a type hierarchy. A final root type has no types related to it by inheritance:

  • It cannot have subtypes derived from it because it is final

  • It is not itself derived from some other type because it is a root type, so it does not have any supertypes.

See "Hidden Columns for Substitutable Columns and Tables" for more information about type discriminant columns.

For an example of SYS_TYPEID, consider the substitutable object table person_obj_table, of person_typ. person_typ is the root type of a hierarchy that has student_typ as a subtype and part_time_student_typ as a subtype of student_typ. See Example 2-17.

The following query uses SYS_TYPEID. It gets the name attribute and typeid of the object instances in the person_obj_table table. Each of the instances is of a different type:

Example 2-31 Using the SYS_TYPEID Function

SELECT name, SYS_TYPEID(VALUE(p)) typeid FROM person_obj_table p;

See "Hidden Columns for Substitutable Columns and Tables" for information about the type discriminant and other hidden columns. For more information about the SQL SYS TYPEID function, see Oracle Database SQL Reference.

TABLE()

Table functions are functions that produce a collection of rows, a nested table or a varray, that can be queried like a physical database table or assigned to a PL/SQL collection variable. You can use a table function like the name of a database table, in the FROM clause of a query, or like a column name in the SELECT list of a query.

A table function can take a collection of rows as input. An input collection parameter can be either a collection type, such as a VARRAY or a PL/SQL table, or a REF CURSOR.

Use PIPELINED to instruct Oracle to return the results of a table function iteratively. A table function returns a nested table or varray collection type. You query table functions by using the TABLE keyword before the function name in the FROM clause of the query.

For information on TABLE() functions, see Oracle Database Data Cartridge Developer's Guide and Oracle Database PL/SQL User's Guide and Reference.

TREAT

The TREAT function does a runtime check to confirm that an expression can be operated on as if it were of a different specified type in the hierarchy normally, a subtype of the expression s declared type. In other words, the function attempts to treat a supertype instance as a subtype instance to treat a person as a student, for example. Whether this can be done in a given case depends on whether the person in question actually is a student (or student subtype, such as a part-time student). If the person is a student, then the person is returned as a student, with the additional attributes and methods that a student may have. If the person happens not to be a student, TREAT returns NULL in SQL.

The two main uses of TREAT are:

  • In narrowing assignments, to modify the type of an expression so that the expression can be assigned to a variable of a more specialized type in the hierarchy: in other words, to set a supertype value into a subtype.

  • To access attributes or methods of a subtype of the declared type of a row or column

A substitutable object table or column of type T has a hidden column for every attribute of every subtype of T. These hidden columns are not listed by a DESCRIBE statement, but they contain subtype attribute data. TREAT enables you to access these columns.

The following example shows TREAT used in an assignment where a column of person type is set into a column of employee type. For each row in perscol, TREAT returns an employee type or NULL, depending on whether the given person happens to be an employee.

UPDATE T set empcol = TREAT(perscol AS employee_typ);

In the next example, TREAT returns all (and only) student_typ instances from person_obj_table of type person_typ, a supertype of student_typ. The statement uses TREAT to modify the type of p from person_typ to student_typ.

Example 2-32 Using the TREAT Function to Return a Specific Subtype in a Query

SELECT TREAT(VALUE(p) AS student_typ)
  FROM person_obj_table p;

For each p, the TREAT modification succeeds only if the most specific or specialized type of the value of p is student_typ or one of its subtypes. If p is a person who is not a student, or if p is NULL, TREAT returns NULL in SQL or, in PL/SQL, raises an exception.

You can also use TREAT to modify the declared type of a REF expression. For example:

SELECT TREAT(REF(p) AS REF student_typ)
  FROM person_obj_table p;

The previous example returns REFs to all student_typ instances. In SQL it returns NULL REFs for all person instances that are not students, and in PL/SQL it raises an exception.

Perhaps the most important use of TREAT is to access attributes or methods of a subtype of a row or column's declared type. The following query retrieves the major attribute of all persons, students and part-time students, who have this attribute. NULL is returned for persons who are not students:

Example 2-33 Using the TREAT Function to Access Attributes of a Specific Subtype

SELECT name, TREAT(VALUE(p) AS student_typ).major major 
  FROM person_obj_table p;

The following query will not work because major is an attribute of student_typ but not of person_typ, the declared type of table persons:

SELECT name, VALUE(p).major major FROM person_obj_table p -- incorrect;

The following is a PL/SQL example:

DECLARE 
  var person_typ; 
BEGIN 
  var := employee_typ(55, 'Jane Smith', '1-800-555-7765', 100, 'Jennifer Nelson');
  DBMS_OUTPUT.PUT_LINE(TREAT(var AS employee_typ).mgr);
END;
/

See "Assignments Across Types" for information on using TREAT in assignments. For more information about the SQL TREAT function, see Oracle Database SQL Reference.

VALUE

In a SQL statement, the VALUE function takes as its argument a correlation variable (table alias) for an object table or object view and returns object instances corresponding to rows of the table or view. The VALUE function may return instances of the declared type of the row or any of its subtypes. InExample 2-34 the query returns all persons, including students and employees, from table person_obj_table of person_typ.

Example 2-34 Using the VALUE Function

SELECT VALUE(p) FROM person_obj_table p;

To retrieve only part time students, that is, instances whose most specific type is part_time_student_typ, use the ONLY keyword to confine the selection:

SELECT VALUE(p) FROM person_obj_table p 
  WHERE VALUE(p) IS OF (ONLY part_time_student_typ);

In the following example, VALUE is used to update a object instance in an object table:

UPDATE person_obj_table p
   SET VALUE(p) = person_typ(12, 'Bob Jones', '1-800-555-1243')
   WHERE p.idno = 12;

See also Example 3-21, "Using VALUE to Update a Nested Table". For more information about the SQL VALUE function, see Oracle Database SQL Reference.

PK>]IPKpUIOEBPS/adobj032.gif 3GIF89a????333က@@@qqq999}}}fff+++iii###uuuyyymmmQQQ칹MMMYYYaaa]]]IIIDDDUUU|||!?,pH,Ȥrl:ШtJZجvzxL.)g, x!Kr(O) ~X=6D#=B"M,&|4-  ?:#O2. Ck=<8 $8 ??:D ?E #$*?#, +#; #'8 'n6X@A >a 4HS,L*~ "`A$t 34HE$ @PxP 4HGTTQ!z0Q&1BP/z@A .H&J3zx0Ō aj/@G2.DZ&zXP)縧vE%Q f`t2Z3N5b 7*L OrڌDV ؉eZ 6Z[IB tC[=\d葁 953E;x@@1~1 HC0A0B mQ@0. 3G =nR*pC %pB 1$M!fv\Yy X煰B( Y W|BuG 6 ``T;D RRhaQsAZbqf9 &`0hm# $ @@ p c[.X@)%:RȞeV&0f&%-Af8ppW `X%` !N&38@ )Q!B$K}!l=5nx *P $l #&@^(lzug_Af %DqW^a4@8A@Z/ T 8FJ[T:C7K!K@ 7TB"б46C@c=,y-FYB&KڠМ.0DzrgIn/<`΋7G/Wo=@UN #/=i3.dhn  {M0: L̠7A~c\ 8H(L!)@"p T +(p 1@ S>xb8 ҰPL ?(D{SJDOh0 hF\l @G@qU>^h1. @@=`i 3APV`  )ģ}񕰔` IH"1H l$H 0#` @R dZ`>O "@(hL@( Z8@*M#ş(`ؑX ЀcFPzcIXβLcl" d:AkL g:P@ >5RQ \P@x@RD >@M1\` M# *6 m0hA !JWV(Fm> N h !4\iJ@)- 0 ,ao@W-(v`X@l/$ Xj( 5 r(׹ >bK,Bi[>pK8Ff 8G" |yd젟 r`@u-le JRV@n@NJ fP | x7 \ 6׹Е..p` 60'h*L:1/-oiAp@d=`\ &_FQVrv0 ``'@!(( $h ; (S8cHxd6qT@`:raBP(1 E@^@HfN ,d0n(K*P\>E t` X 6!~R ؀^ 0U,=7Hcƪ >@xX<pI MϡVX% *0 D4K+w*knj'8@ " z0cgp 5@OT2x"4@躗   LW1 r 49 & P@U} )'ؠ Aq x @2o$(ip`.  8@;`u?w̽ug @@~T-`\pj+wҔ.5$ 1@4d4*>h'5`}lmbXc#a@(`k}[x)P+7!`+ }$-0kWxH*z"5z6(@cX)|}׀ar]! D>p/Og/ֈ& _dlD,|A`@r3pl0Py`7T W$ 9Dž2pC+90[Q;'Vw($JD`%R#2w+PWY5v3``bI"`+ uM`uPj`W0`=G6yډA@iwPm( ; 8POU0!FAN (p%T0;з4mI'a97U5`G4.$0 "kG[& P6P!%].`D9sV7qg8L F4 <6pFoyX`ٙ"j%oA_ Ќ%'`XP2 PgzdR^IÀWp E)F"F)1ڝSw!Ts1CIB5$Eکè}䁞AzZ8 #qDAjbXie\:AZګǪ=sc!ڬZ>"z'0<ؚں:<dXp蚮꺮ڮ*45'72] [{ ۰0e,۱ ";$[ %۲.˱4/[6{8:8Puo2B;D[F{HJK L;T+aRZ\۵^`b;d[f{h{eh0lr;`j0t+  y۷Ybp뷒P{x|v+ i0Be $*;cй s?-ۺ^` ?{{W.SP*SěI0 :551 `̛Oc5ƽko۽" ۛI0t˾ٻkދ{Ck<\ @k#\ ;@K "<$\&|C,.02<4\6|8:<>@Bq A0=@B'p/'d #ʹ#>üR@d,4 1 q&6\rBt0!բ|1!qʩrGB 6EHJJ`AYEgZצD80DAScJbUOf|< PaV A,Dr 5ny|$ϜHBv*p@e_G|'`cCG<G\P1 D8 $ҷ@@ $4>N&V(0V=%ܿ@{7>@30`E #Pf/`+*TDu=}†>^VLˉ4Ǒz|ia%~q^ !{(r~z8"3rzH.frf|H|40j|xf@.(*L\D>|b.PV`XJ4 ^|8^f bZJNS!$B( 4&+/9=$hG/pJ >x"&HW/pXe!|vFƈ|dcCF(vaB so]gt_ *P`є`ftAy"g$0 J=4(1  q0"2@ }~:Q?BXA|`Th`c)2xa3D@mdj4SgNDDi 6z聀P!zh`"`o@b@@$!@T zHmBXx@xу*8Ïh+RpL(`L@, F r(AKgj4dr^EvPla*0 @ 8h|x.%QL :X 6@aDXń: ^  L0 |X`8nnO-5 f @fpPs!"CHSm`Z 2q!jH&`f.X4"!ⴂ @BAj+(&Hr1PwUhȕt{A b  ~}P!ZA? l4$(gjA]Xc,<@ yZ >g^ j@z " $Yʣ Pa>`baNƌ@W@N `L 7kR8E, =ہ @@7A즤9yti ӡ=a]D"8@L`;y Xx^2`AP ˙󮰃JOG>-=>X|pM@ l: m|p"Ѐ,0 l0SP"$ Ӑi`E;E `t$A ^9Р&@j^D "ĀZZ^N@t Pܬi- Hp>>SH109z A@P9NmZ4 rDfIĂPs]oĀP,@lЃ b5 3ABF5R@+@J@0@ *ЂKU({ߵR&MCq6X\& dH6&;d%*@!` V"{ws0~Qlp  x ND`g rncҦlE]Z#@̢{q81gY.pLw@'(Aj`Z- LÄ|6 `b"|e./[f; :+@ (Fa `l]A4(TR 8ILMgmJڎG&6$"I bH h"' 9Dk6>alp#"-[v PP/!}Kq[.Dun{]o[ӥmnDzj1qoA9r%+=_/asϜ5ǚ |1GKE7ёt/MitO}[5 @I :ve7>vU",wϝuw@&Pw>YztLx/w!yO^1yoAz'@~X zկ `Pq{oH7|/2( ҷ O}7 w_ϟf0!۟0P\F>0/ @p)1p 00=0E %pQpYP(" dOioaxplP`,6 Bb/ 3PG< 0  0 o ѐo@z.pPo א o1q  1qP-115q9Q'h`,LQ1UqY]a1eqimq1kqUB}1q1q1q1q1qɱ1qٱ1q1q2 r 2QQ8`@!~` 8`16fPR$h9 /(dR m` `zL(X.lz@A `r: K26d fD%z`b%zZ!zx@*jn' n* )rc F@b'n(Obr`DN@T`*j~`e&a(@2`%6/c `,R\`R  Hd`, @^圬8llv~M H@&ۑ+^`$&`BB c0.tʹ@F.(&>UAA+qHhڄBX"2zjz<$.fb` `@XF<z)/@B@&"f(j`e6_3/B/B\h$ T*8ftj"z- `z)ó+L Dm ='"ғԴZ$ rr.+TkXb^`@uz`. z`Zj`H{J` r({@ ޴zn`0C<(f@` <`GG t@+7~`ru~jNdh4Hzڠ VTl%QyS DxRXE<@6 <_x':TD h`XtD[L˒3Q`?@(#&E^VE@ IEj.8t(.`@AEFJMk<~oqb0pb~@NB68@>@ruC72fUfrj~*<3lb7BTPoe.z%6ds~`q L0 CU蠒4@MO(wku d,xNdRI jjJ'tCZp b@2D}@V_{308bmRL`$@\2X2]V؀үAj Aڗ. `L`0R+!G[@(nDKS2đrxW@P*8/DTҗ$/a`N8'๐/&8x;@v5x鸎 9x^ /Dy> !-Y{+ Za rtT8GK@W|%)z*|H^{L@Tg" nbY(5JtT;&Ds ">.`Ĕ")e"*˓K h@+TSXޡB!xD`b%1*)$*p 2wVBk|@!r@melZ@tKx&FpGY7t7Yu# #9 < cD-c4kN `3h">> ?2`??Ie w@cHAH3- 1pu$ nB=b?$b i&D`F`0"LIIIDJJDKKZ$LdMڤ$NN$OO\P Q1Ԡ3A: C[ >g% XZ\|.%j.@odx V W0:D Ze[[e\o6`PLW^^e_%V `fa&&b&b.&c6c>&dFd&dt@Vf+7gv:pflֲrx`\^@> |nlj\`пP(Lhmfnn&o"> ,6Lp'*gr$r,sdst) Dtvh8TRZu8 vfjvrgwLwЙ~`'l >@l. w# )z^t@e&%/'ho>(Ȃrm YTT[` 6GkHrpHN6Cl3I2"_r&ȭ|@ |1l>jp0  $;=`0 x8\,Đ$ẗ`D\Ȝt^|pT0h!8<Pp40.`T,QT8 hk|$ÿ'd9 xh$|Ɔ0`AG>$ؐC jl .   jHxB@"p :˩sL7eBر`!w y =v P‚&88 )\@q z2uADBX#J3(1@1xLdQB@+ `k EfqV'x ÌYqXd7"sgxΟˣg&d2 DPc5<@  V,w `dI "0 F*4fi@  0Vrѓ0Dp  dCB-(2@ X0C6 A  2Qn%D `C@5 >P@ .@Pѣ &@yV &0@ "<@@P0=HPA5P~3h9G"p `0 @_V\:1 < ~)aN.d@ (<`B%c&x@!԰k @# >C l0C.A̠g(\Ӻb{,phH b$aā#3Ԫ m} [l-$lz΢2C8J\qbti1!H@++0L5T@@ I4 j @n 7CWL1{4b$0  @$ d+ 8A9&@ |K@S+{gk4&M@o(Hp\@ E|7ލ}9=85i?(C"P7’OthKʹƞÎ(;Wyk:n1sv;Ne|0SS_c߃Py {0߾ϘB͟s F   h"0 \  0\`g  H+}(= @ 0"! Kh0002! kh0:ܡ`(!( j04'B1R"XEv@Z"/1b#˘`A-&IN;1z#?r$  *\$#G>R$%+HC"Ғ$';I $)KL \%+[H|%- JU2%# 2ǻ0icB,S2Ϝ&5sY.&1ovR4A dNgv\'!9_jL;;0--1-.ussgee?;/QE$a8#GxV0uسsٮiBO<@P}L@`Q!D @xd6ڐSAP5bMx|wI \PS KsEw0`` 0,@0r$쒀$ Iig2 D˔6WlЇ8nx@ę$$9% (sQ }DCwPFeitC4Hh ?zG7ifK5Lޣ%PAw2WMSRJmwD"k19[\ }0AUQ*͊jDPDPxKlN$-@Fa ܪu 1 4"" }orJ: 9!G``V)bi0T%h`[+S77")߰ ж/2ތ{Uv P 줱OC(~'u\TCAj98Q $=M Q[9'Lvശݕ'X 4 ; ËX k3 P 0./5;P8 /=<4vs8^uT68(-Ttc bNe"@<@yfk;$4@^kY& -4|`e(6A dd Az a Ѐwuծ`>gnK^S al6(JRL[g"^z`_ wГAdh&2Y[.ΐZJV d$3,bdA> DcA=]cnصIANh;dH,dK Ē-H؅%/MI29Ќ4IjZؔDf9#@9I`&2;0:7Iy:(k BІ:ԤE5b)0G| ͐N\`oĢB &(a@ ) $$s ;,J| ƁT)T;1]aZApN LH(>V+&~.൯+`0 v ~9lDk2>|+Y嵲JpleuY$ hGK^skqֺMmX\RcmY܂Qmd}K*VA`L{Y̸CP)*IaU-,STYNԞY*?EHmv)H/,4 H @Tg ?ћ'%-'z[;zָOXEDKyB2&Th*vW'.@C8m4xcҟ8rT@[@`]8S(QsURuWm.)Hu(CM) U@3sx F _4U>m됞K;ݞ` o[ϴη mb^kN/e}+_jV 'w[axO<Oqnqq%rZ#50gN󚃆`2w@ЇNBGb;PԧN[XϺַ{`NhOlpΕxϻO\-OQ.ʣ?HS[0C=Oyx؄+.>M' N,+߰Fq Xt?]‘_ER XN1 .-91,? /GƘU{Y(FhՍdJ}!@R{i7GfD|" 6 !C9q ^2R~S~hr ^W?xf!z$ha+W+H(-W/H#6V/u#dTl7?=PE̳IOVPR8p=`nsL;d{}'u!;PKv^'PKpUIOEBPS/adobj019.gif)5GIF89a}T @@@/// ___ppp000```oooPPPOOO???! ,}TE`H,Ȥrl:ШtJZOvzxL.OgnP| ymughi±ș^mkok  l kn澕n:hx=wt_TE `ZjH \G (nM{:Heɜ_G8q9wF uͲ yxΞ r S&9*RZ NK`lc=$8'iKV(`>մdYJVܑrb0sxũ~@SMӡqbL[pR@PR [[+^9W|29sJ5qT kicbϟ~ueVX@Pґl}Shxz`M69RG[km!t=VX# |UZ+ǘxJzmZ\+MGvԱReJNO8iC50v/YBU %$f Ȣsz'NQi Z 1og`9ReeȘ*`%cxN'̱jے&gZ&E\Ւ m$, q p0v~,@a3RH"agfP+ZΜ{ Sڼ:X+ѺԚyx!Pu/Pzec9ջd9A7n'\r~*.b9<%qN]@ߢo|̵JO@ZSJ'nf\Ց҂v4Y$ǵV\Հcan]4}salMݘz)]gtJmdaEitO -is!F3jNTGsmpdV9%ۧS}M޷>} JmuC=9FaX"p7e IO(yO>S滧t&I&8c c_?L(`"3J_e.O $>I04$t&&D SB8,0AH8̡ !!HDUdHa&:рC! eЊĠAPlP࣢(A2Bk_@&QbLj,ZK7/x;nF Gr $!C4ީG/!5Hd'N~(_+Y"#OZI.;bpdӥ-}9-Q*/w)%,kIr$E/K|sHo\Le_t(?)qM:%p%2Q=H[BkOL)âҔ M\"LX^&%UBPI2ijA'S| UhO!* p~s V€tDTM&5}u7$0dYjuD@#*gX5tVpLP_Z2de=i)XK3x.-ac:4S)ӫ,\PZzEMZaZc_#_Klf+8vn smMdi7+jl[⩽'XR0h]ӆ7YZqC6n&R>[wQA ێ 8q'O g)Lk΀qxmN@o|m8,ȭ)_"!NlNԠVx%NkȀ0<!/Mݲ5q=~."O{l7 }w¯^v>w1>ƻ?n3S⯪Tv ́^z-o=4bW"9{ίew0ؽRe1 yy^)]fCo+ѮJ4ϫ~4?}|/Mb{ ؀ x!8Jx4؁"8?r2(*,؂.0284X6x8`<(dNpЃD(^@QPJX?S pKR p0XCZ؅^`?WWBaxY҄}e0hU v(GX`fx|y}GC(x{ncc @;(B&h}ȉ(^X(^UX؊Uo(mxDȅx4xЋ ČHX7nyЌݘrp78'ڨ% `xx!dy H 9EUX%8 ՐRhؑ"X#A&y*YoH)̄](Y_69E;i?9XCyHy/ KYb(NIap2`Uy\Nh0]i @`@PȎPh|z XiPia9 d Pؖ I_Xoyp a0b@ 91 8Жi!F!pI;Pq0n)BH9Y@BF™ I1h 0 `C@Z@๖i nvٞ90 YwIi0 Hy 橛x\؟Ini8Q98qA919y6z ֙Zy iC`9][Йٙ^iHbS(f _BxtZXPzPp7x B~_ xG`퉩[ Ʃڨ#sg::qwa aa2#A5q Z0yruIB MmiM|IƝ \ޗ,!߱ pΫ mO ,@o0  ݇nAX8mh n I%,uS(N`)<\V>ٴ1>䥚@ MݱXCux0P^#-a~Ѵ/':ye~epqMY3Vl|X[_pދJɝ2j_imڪ=Rd80C=~ d-B(/(oAWJxtH J=s(c>=bl͒d{.^O*I. ~s"Q/]~sų^HT۶VZ_z_^GܐU/yuH{ٞ`{~ ykQжȷ]3O1R@Am5 O-kؼ/s@S,QZ^P$TtOGv vq^yΙ83 > ,:=?ACEG4UWYU[9IgikmoL }!#<pt Ⱥ;< qPae@4@.7ao>@`=8 @!%4 QB-t K8A ަkl8l@a>T?94O`G9 p1l:dADABE .!$#rF9G9*t _mQ[X) HF,*8@!pAͨ8<9 $jP!fHBҨHH9.I `q[tWME% `'O#2{hIyR Ҡ~b&N?E5Q@U@`UNU* T t)UDcW”gOX"nE>yJdtuH ѹz ]A4 JI̛v/XfxFӎLl `QͮBxQ{@f$U`t ` YxmefپfB/Jfh#.mQx% yU(W]~ )M_s4} 编Q+If3+JMWvQL+97c 8ascGX;NF# Is'i4 3-1A e! yIc񏇔īE62ŋb8(MQ$P[MHnd$$顰f1J%3dOLt @md&':}!cȨZ+O "JBԍ 5);x $v4"0f 0&Vh>,•+\V&2$r+ yaEzj>ԗ4P7 vge iIz~52RFekB& MXTyk.= 3aǽlp⃮"%ûx,ە[[ l"`Ϻ{ ֎I@b@( i!gP b.QsoҮڿIOf^4 ;aaFlC,97 mP÷&,nX7-NcY[ۼr SzMq 9Q(WڳvsKsZg-@v@[Usn1yo^ 7EozX@&w]g7jb|fϞfyoq|TV[OtJj[^IZװˉÙvAכD'O %"Pƿ避ST 6:ajh@Ad"8@%*Mlb<"` >zg@!j:(:F\dlp6` >OdC Nbp&, 9Ǝg$@8h7 zf $`l  C!@mb2nNdm5> h ,%z6`v撔@i$2<@ n @t;GDcHBn BBژaxL)B8"缥EV 1tD!Q&LnL@ |k(Ǣ@Pܤ0qĔ>Q ½|  @ՠ@,d8 0q֦8ClPf. 30fdW ފ *Qd`aEL+(7N Ql.)In 3@A?z_MȂŶ/vi"%2!9$1fV.>y:d'cap<(ؾȀ 8)2*a .HH++!nrO @7*&ѐM<UK -  䰤n2|E)qtE1T+ohΏ&5*EGEÉ2 &90 p+e:A/(6fNj|cF6vW28s88N)RA n<2&eS s&83ȚqJ FXܳ:IRAF3rvo*R :`i@cs%Dm`PBA  ӸA+hX4 &kaSZ^)2ItIM@B/$ü%Ă2K\sK,! f-)?GRdMvE5' Ft8Fz&E4~tR 4PGr,H?'TE5bo*)N@!GClc1lcPI.) coRxʓ>4~BFA>O1cZ2-2q.rf8N ҆8e1s5T ڪC;4Xm'5C9%'$a^^#Zg U@61(OVp5P|#rXCaE.ݲagmg9PZDO8ISBc5_Y6hVI%eqGcf \8jAUAz$OW@*m Q@,vlV,TaӤ)oF%"jH0 .dyԠ("6Vͬ)3ZFԦlnnȯʡvTQˡFs:nIc'?萎FY}$o{voJ3 _"ڐv 6f>hb*b c`UA2h 6f1.q LWW-x0`:5x@Q!Z=3Z >|tU{3u؉dc|w>nU+ow&d8 8@RunV3WU0FT ؤn T 4p vR:m$8z2fRn o3`ׂ3nA A7rLĆEDo!붃+ ;qy\gI8FxD^醗A6tƁ/rX䂏 Mz.z`@D49`Yz!#62XB5\wy`:_7v#yxM`4GLI8hQ%a$ƙ]i muأ,Bjh׍ÀG.rY⥤e86]'9f ڂ=tvHwl*dF)6<&"؃pv.Y)j{ `#-0YsA"l]!%ݚ݃qw*2$\++;jiVL jۈя*/ 龑6Vb5[iihV'^L#Yu@:N^Nsg-)RFV5`JsB0] ڷѷ2x =vsx#ŷ\c" XW|=6fL8jٷR^ng6{~Kr[˙J̈d72;밾;ɚ:Qf&0ȶ!M_[y,n@`D  r1\/ݪתI9`Tm#p^"%d oO YLP&9/507$(b2 ɢ#'b¡- f#e<= t$W&\î,e:QLTM hU*%#tjc-ߧqb5wfP ~yY'4?f5Tz=kq6QE͆b(/ X@OKbjf tS{;_)˙J&Uc]S[Gϡ7)sٰ12TDf)Ht-~D-YH#QI;")ǒ#Hx"!43h;B) jш Ԃ>U h a%*!瀇jOÁBBP,WNߡN <Cizx wAVS5́$$KX}(R B%Ш/טa2 0/ A(" IM !.Ȍ7B6 pOy.2ʘ10s`:"ʨ<_H/!}H-9!Аz `8N0!qOLEbA(4>x,8J 1x&(X?P9: A}xNh li ͱ()5+2"r8mI`Ӌ*isnٌWX;g4$~z),|ҙw6`|𘥣_5"Ɓ!3 GYSғLmSbx!qHXJ1Ʊv fyk`s6Z9aq\sc Ԡ$P``{qfm29zi,}t2:27| ej 2N4b320%a(,R J8ʡ]Ѥ5Qj  eY1 l}0 [z*c x`gJzekZtizoym szmqjwxu{fyZ x}^ ZtX*WzfIpt;7ةZm01ڪe:ZZyJmgm݀֨j:|lr pZt܊ʧz^ 0k `VW3'ACA}*uզj39E c꫃)V3z X [*(T0e%RI]䊩BSӘE>FR 0DgN3A [g \2$h,A>ZۑR +an^*IL̤wxy%S49 rY(~!4"bo` 0O'q_۝ZITB*FpD` I+Aд%eT+4an Q>*XRű8b  Ȋ1UCI(D$90 Ȍ8K ;3014µxffh]#%8뵷*e$,A" c24[ śC"z2"ʫHweAK->4H-Fh`_ g?0}H%+ ,ˢ09õ}iֱ L1N/{b]-BS%*$g[ЦoA!)O?0`!WaU?X1!Aj'rR> 3IAmj Pq&u%d a5q4պQNjU֪Ëɶɂɹ%@.Fʊjʐʥ<[̇Oƒ~ N% cS,rQ)'%q"|dL5\?'|G 2RW3J"u<<+u"GRp g6cq'N1<)-bU] ΐЃT%2 8e(]3#o繎85Tb,stQ,>P+aji3 B"4MiK9 ?;hbr88)4_݁ f1 О~WWUFم%;mѸg0>X$RQTbQiyG9-#&&ģ/Qos!дT|ȁmہWb])S/OMg|=SJCyhC@ZV~a1iz0[^y|^ <')/135!$7C,EKMO:=HQ]Z_egiW@kQcy3UsA:Źn$+n8s &TaC!Fx`E1fԨ1FA9dI'QTJ/aƔ9f͚-mԹgO?:hQGiSOz\jUWNźkW%~;l4aͦU)ZoƵVn]wGŻo_~F`ÇF1V !G)Ae (@x s* a  XpskD?`(`̓ @Soi-9\l! Hg:dκ|N[ÕR qқᅦyoB\o($%<$-Ϝ#A]I/QO]?Gs0]\b?j]wcw]*߁(9?䕏/, *l8_/O_o_x>sv XWd/@f`Nh` nr`ѿ8aZDB/LqD8v >`napwtf(B9B<A XB9< 7`4z`M@;PG"l`#~  p $p`YB(nG~@f@@)X )Q!cw#nс1 ' L! 3 F"ؘQ@9l ) Nn"͐wG@H@ԥP2l 1C#6>pO0ai,Zq"Mm09#$2 M"2)@0V3Q$3-d J5d<hI330(Ȁ6c'1FR@ViYZRm7oqC`#$@7UAhFs[B4׽ fL.0J$pD^ Ul d:DBOJ6pk< @7AhA e8k-X>;$#w Z߅iVtp+YǻRUp[:FΕ%1ϙAڀ7W,-jˁ{Ғ~ rWqYdNg\r|<20n&nj;2&Fy9lf9|Qa(W a怏8@o\0KH;m~] ҠݭorJggo=a"5TNJV$=kT|M`%Wi!Tx e6 yz@}_B ˡO\:A]xꘗUz4i,v9L,RRF0Y<oz̍n5JߑfK!kȎv{qFmvl*c+DۄCSrs"~+&2(C(0F}g:/6g;yAXBxLwpB4%)H_A9g]DѪ\0Jx0Oi9m[FHfPl~T)@ǘf{/ɨh3D-`v @L+A]ƺy04A?LnKGGFR̢9m?|@2% aP ~#}rh 0I`0 ,/ML;!toKhH`Vʍ^mP RP.6yU+w}p[(b0 p G )H ߂ p  B 0  g Ѱ OA ӂ OepJ` 0 ܼQ N 4NoH|ʐ! :0O@ `DTĺ x\JŢ Ε`oѠjk _ 鋊hm\Bxo%$MkL͢H4? Ji ɌnF FIz(R *͇˽j+0>r;ˢXi>h 1 "M,!'E#m @|JVa&kzH ʛ"Ol(+-);`.5*ȑH В\Lh ˑP,5I"9i NQ2F! " 0lޠ/Iь@ͭ$ +p 130`rɍn~R1}ihq \7aS֩9&@Ivȥӽ3-q\,Trɛ 41ˑQۤ @) U̇CKp= C/TC}%K2T<2܎n=29i4nrTG}T0K(HOk~t4IpIIMI=h04Is,JLtKT,$˴M4Nt"RfTLG(LtMLKK4MOPEAP;OuPQCAQ9QQR7AR7RRB=Wr2<5y!H{6=+@:͒ JU,1؜MYO,IPT|6i8YK(VTmm-޲I^( 543v U&MxU^HK-?J]|Sa*_ŨVH\TK)P(䈑Xs  I6苘`@3HL6Tu"dKdh8k/ yO988IXXUŨHZkp"_rb a}vjg/8YbT tSj6hdkɗt h(j`6 mۉ"G j*b\1HrU;+!q[_qRv1lANT"57aE"bIL;͈$\؈YMS%` |etS5AS+{|}3A})}}~1A~'~~qv6WS qhpeqg w: @O.8>b9U Hwֈ 8:M@+rz \Lr͈苮q(N !n32(aZVx $ -lNbVr8hB-$ǓD.*ɲ*vxT`W4InRIJSo>QꞾH+Ɋ 8Řk?)XIi!gSgXg)+GԘ)V<)(_k |§XTyQkӵ8G 6?}3ҵl62.\L6hnK"%X䌒ю.9iw2=Q`)] eg kxζ4qZ _.5$׃2y r )2x/_+s4+Zpj 񌋍yӧ9)V+nR2-qx6ɫ_: mVM@a8C1BχblPVK C9r:/|: HSE3VKS0t 4P{~Q' +;Q/{3R7{ ;;R?{Z )CSG;K;SO[R{ W(Z^c w(z{~;r (@~{~{'?zMứ{;[(½I;w[뗿_ҿH?H]G}:kPÕ{Tkb=%< Q'NW)2>ڷ1<L< g|'@5| 0a|Kw5Y&J_{\'j`ȑ|HқųF˕K^ȥ( 2 +M69Ѱ 2. ),"<%% >1)t\ IË@pI {9У@8(SZ F< @b@HJV*(iV )zx+  C?z F.¼T&: ++<ҳ=   ب1Bp`>r8E^ j4Q jB %K dŰG &~GrdA4Vz^un|{q@y2e+XϾ={"T RqD @r-0$LGB C0@CY3ކn(C $2a=VR% AqI $5I%XÊ/D^}yP:0XЕX^iA ؆A =t :BȀ0ܠ&(TC]( d袊^A̐j>&PB#Ѓ l`n.` `B@ <1`Ѓ B#İfMx JP uJv/T` {@h0 @C &*vF\C* &@0ŀT1ˁeíC0 I!+2a8 0 8tPٵSC x wv. `A#2rA@>tÌP(pw`. C=@ 1l%7ۊ:h4"8([M=Gի0B|Y @8"|mL,S#pVNEBp'Yn@&B7Cr BպbDQa P%<& `0 Ȫ0^.0m=+3gu/EVS (|@R`\8<˸``` 63qP3+TV,!AJ @0L.{hTTZz @nP@!b)HjZlH"߫V%5IR< @)"Lk=%(,MPvD&52hO,h (OiFTL+?7[0`РUY#4TW|H>0[0@RDFS  T`{#,`4l$4`?ր/hH(e7iVJW 8'L ʿh\8X.@&_3z P*(tIQR_<P:Jш!z-փȀH1. w"@,?aޫ 8` L ^IP`@U-P^`$`rr2p@7Gy>6"% ^C01Д6 00=‡+WP/<.2G0 Eq};)#@W9w~NB!\03ّq"j*bzxmt'i 8*)'*)@0n2`&xb)|0Fa&(T>:papA(L^EP]*ra6=s1"p`Q 3@9`?S0 % v3p5yp0 @ `0xh+Pc ؏ )f&MD c7  iM pg c[ D0YEؑFtPvG 03`&8e:A1J1Pb: .6Ka#FYIY 0O_ `/0 r9{fGK0T'Pz9p$٘N(pJ1@D`UAIɂF`mNyY 2 MSITTGR J$uYy[pUTeCUɜp9 7 EPG pPVtii1`%ZI ęX'Upr!rٟ ڠK`$#: EEeD<šC Z5%=&??@,T)6zjP_CH,@tEWF*r1@sR*1 0C`7[J 0%p ڣ0<Y_`4 p*09~Y4>Y{y?Е2PPli10.`}dJfB +pɵ\QD(Z]壌]-^0O/e:81q_ z!)ZIO!iQ pQ:}z56[Ъ  vpBI[>&50 @ѠE dhN iZCiOd B  ˳. -6^oP : >6.0Pp!} )T 000&liP )b0y."%2 l )3`%h*?`DGbsy( #@pA&05aU'+ P`- 8,``- t  pp@'8RلC& `cRB#@5%p & lW'w r rxp We#8"+@b rP9h.,t1+:iװ "6Ԯ@rT'z*-#S,SA4%*% R"7V ?"1J 635 \s PGxp C^ d T9*:\'-&8[Q3`B9#@ӥˣ jPL=U98o00#`6I2+Ca p'|p``;cM q?o J``Yv I ]fJ5 ɐ20ZF6 4? =bN\{:Y  O0ئŨ]Y` ԛplD,[V9'B^6pn~;Y0~+"KҡԞ`O`>SZEW4=ǰ7B<_ OiU䱢08z6 #Gr2i:G@L|&azu`>2*D P?%TdX\0`?1tdT;nUOGX9T. $PDS4T82Ǖ _X$%92蘟S5@2 Ѽ8$-F@%\h ?Sna0gsi&`[<QKE5铃'bn00-p35..os5C}O76Pr  W@idE՛qzTHզzYOi}v@\?^y Rz{>(z(^n$Vn46.P6RL&V&zJ:z`,*zZlo y{}*X T;|"V6(:*|T,^PK&O|4n|,z.tz&|ztpu猑$F"ScnxuCč4ن>'QH:xqǑ'W\y4*HqcmΓr80|yѧW}.8v}iǿ{ PLlpP  9JA 1E,_H8`SP[,@>A.DTIU R1%]CT\@ Rh0P \Kk4 `d[`(`0`uE# "H@BP@H8G "!3^h؀5n(a+$ćz`Ѐ 6x!)T}XuՇRZ|-շFDIy!``dp U" L!$w1jh̥ƚ".恆w}B juuqΕLXnb@e@! N(VH!:"hKNESE` V&\C 0 ):/H "`sKT fAA6΀$ i@&:(еph`gf8EPEv. B') CzClC SJ 0_S.%@ Mlt1(O"D%0(<@ ( FVѩVGB寀 0HYعϱ[ d$+Ug2KpjZZ\L @mq @@0\{I` _n,h!F3{eWnw]KUy )OeoWaPZ `0@[@-pa O I4Zg%֪6bgHp 'X$+AO YyB ``q@d`lL5@0:cXPe @0aŧ=@% P ;HAnѺ HI4֜bOXpH  Xp4@UBG @dS>:@|B.pa q^' .0~@ 82BP@XU! l f5,5" 0` 6 38pwAh_di+`d"|/m%(x@0`*&H29eA6 HNXhBINPNxy,|`4 `!վ^^!TP` w8>pD+Nq, 8A !x^  h3 F \h ` 7:$ 46P4&`^ ^ӻWA@ @ƃ77 օ@>(x`|"@])4$u{ @u'8$ \rBAp$˷ PA @!*l* pϼtO z|&@ >@f4@nE{  0lM4 \*` D :P"`` |4|֮4 Z#0r/| )7. \6 l h2^f B*0, :@YV^(&b $@Lueag Ύu r@FD@>0ͺKlP`P4`I  dNB| > q|b,p̼iLj@ ̑tL,l8@t@1qD`t 2!H~4;PKHo-ML"G"PKpUIOEBPS/content.opfs Oracle® Database Application Developer's Guide - Object-Relational Features, 10g Release 2 (10.2) en-US B14260-01 Oracle Corporation Oracle Corporation Oracle® Database Application Developer's Guide - Object-Relational Features, 10g Release 2 (10.2) Describes how to use the object-relational features of the Oracle Server, 10g release 2 (10.2). Information in this guide applies to versions of the Oracle Server that run on all platforms, and does not include system-specific information. PK]oPKpUIOEBPS/adobj025.gif* GIF89a*@@@???999rrrࠠ000 ppp```PPP///ooo___OOOvvv<<<!*,`H,ȤrD>TШtJZجvxxL.M@nց E~ kpQr~)' $X *xoY}WȧSЍSEOs{uvшS(p(Rt ݍP`Z'P Hp "@@@9T<`!@LphS+ #PxH`_#)(xALP`(Wy>A_63 *0#PA 0Bqp Dh! T8Ո lS8:x(bRx)C(`A(BN\( ;(VCخދ:jk3;6_N <#P<m"b:]bPEd3u .E}le WVp%dW-Om?`Psph}akw`Rq` #(vnXwX*㐍UA` 59>Iz'#""W@#@zRTC\pA8`~_Mp(@GhI&yl+hך].p[[r#`P}hv@g_-մPڔN41S뭼+-[l(" ˫˪ҬA-(Rˈ+X$B P+nl ,lp 4G,Wlqđ(1m},_5A(KG̠N4LHZy@;8m<rG7=EDVQ#T\D\gN`GuaMvfuj;vG wrϭsvӌw.7~=HIn'x=/㋇tQigo.~ag"- cZE # ӓ%T79F: FCGrE"P&$\ҚI'&qwܹFCfP)Q|YX" 3wcR!Hxh8.!q <0ix `R0 nǏ\PNICS( @hЄ Btf.Uq4)}D"J6&& RO6 X9@ITSMȀ4e<,–0 _p@h i!XM wPCXȊŒ(N,V$8kL) B! .(6%A RC‘D: 500 gjH$PnTֽD@f Ozb,p&8|!>b 6Vt72]Z5Bԯ L? ׳0桴{ KAhW0gb$k:wXp@d EFqFM>Y(k`74jyY_Y|+(d.VҬ毱yck~s=,fйŸ3{=Ӣ~^A>'ݬh]%фxt2J[zӠGMR^}T ÿSV62XW Т<iABY G 0}ImAB$" Mar\f'AbۓqsQQk-.-D㰫 DZ`PbC1G#ݪRf#;CІ+;Nϛ wk=ϥ#cY@y$HKWx{-IxC.rOe osݶ+0;D\Qn\ ra/MdW-i.)dU*8V%\5Vdj tIezyo{ >~YdP I(ME10~5E<;VP$[PT̐CԴCҜ'&`>叧 VaD&#p:3ɁuQ>*67A@!*"HwUtP"|g$|>H@f< $,`4d] `\p@xWHjM6*PUURX_eY2pPwYR_10% %Ovڐ"LӁ\!P@MDsFO@!s=WX(ЅWc( CTEנBzR(SbrA:: eZm2VCGƊ6H68:3è-H3fj،4ix#6Fc>֍c5Xi蘎XdA;PK'/ * PKpUIOEBPS/adobjint.htm Introduction to Oracle Objects

1 Introduction to Oracle Objects

This chapter describes the advantages and key features of the Oracle object-relational model. The chapter contains these topics:

About Oracle Objects

Oracle object types are user-defined types that make it possible to model real-world entities such as customers and purchase orders as objects in the database.

Oracle object technology is a layer of abstraction built on Oracle relational technology. New object types can be created from any built-in database types and any previously created object types, object references, and collection types. Metadata for user-defined types is stored in a schema that is available to SQL, PL/SQL, Java, and other published interfaces.

Object types and related object-oriented features such as variable-length arrays and nested tables provide higher-level ways to organize and access data in the database. Underneath the object layer, data is still stored in columns and tables, but you are able to work with the data in terms of the real-world entities, such as customers and purchase orders, that make the data meaningful. Instead of thinking in terms of columns and tables when you query the database, you can simply select a customer.

Internally, statements about objects are still basically statements about relational tables and columns, and you can continue to work with relational data types and store data in relational tables as before. But now you have the option to take advantage of object-oriented features too. You can begin to use object-oriented features while continuing to work with most of your data relationally, or you can go over to an object-oriented approach entirely. For instance, you can define some object data types and store the objects in columns in relational tables, which enables you to extend the system built-in types with user-defined ones. You can also create object views of existing relational data to represent and access this data according to an object model. Or you can store object data in object tables, where each row is an object.

Advantages of Objects

In general, the object-type model is similar to the class mechanism found in C++ and Java. Like classes, objects make it easier to model complex, real-world business entities and logic, and the reusability of objects makes it possible to develop database applications faster and more efficiently. By natively supporting object types in the database, Oracle enables application developers to directly access the data structures used by their applications. No mapping layer is required between client-side objects and the relational database columns and tables that contain the data. Object abstraction and the encapsulation of object behaviors also make applications easier to understand and maintain.

Below are listed several other specific advantages that objects offer over a purely relational approach.

Objects Can Encapsulate Operations Along with Data

Database tables contain only data. Objects can include the ability to perform operations that are likely to be needed on that data. Thus a purchase order object might include a method to sum the cost of all the items purchased. Or a customer object might have methods to return the customer's buying history and payment pattern. An application can simply call the methods to retrieve the information.

Objects Are Efficient

Using object types makes for greater efficiency:

  • Object types and their methods are stored with the data in the database, so they are available for any application to use. Developers can benefit from work that is already done and do not need to re-create similar structures in every application.

  • You can fetch and manipulate a set of related objects as a single unit. A single request to fetch an object from the server can retrieve other objects that are connected to it. For example, when you select a customer object and get the customer's name, phone, and the multiple parts of his address in a single round-trip between the client and the server. When you reference a column of a SQL object type, you retrieve the whole object.

Objects Can Represent Part-Whole Relationships

In a relational system, it is awkward to represent complex part-whole relationships. A piston and an engine have the same status in a table for stock items. To represent pistons as parts of engines, you must create complicated schemas of multiple tables with primary key-foreign key relationships. Object types, on the other hand, give you a rich vocabulary for describing part-whole relationships. An object can have other objects as attributes, and the attribute objects can have their own object attributes too. An entire parts-list hierarchy can be built up in this way from interlocking object types.

Key Features of the Object-Relational Model

Oracle implements the object-type system as an extension of the relational model. The object-type interface continues to support standard relational database functionality such as queries (SELECT…FROM…WHERE), fast commits, backup and recovery, scalable connectivity, row-level locking, read consistency, partitioned tables, parallel queries, cluster database, export and import, and loader. Plus SQL and various programmatic interfaces to Oracle; including PL/SQL, Java, Oracle Call Interface, Pro*C/C++, and OO4O; have been enhanced with new extensions to support objects. The result is an object-relational model, which offers the intuitiveness and economy of an object interface while preserving the high concurrency and throughput of a relational database.

Core Database Key Features

This section lists the key features and concepts of the object-relational model that are related to the database. Figure 1-1 shows an object type and instances of the object.

Figure 1-1 An Object Type and Object Instances

Description of adobj036.gif follows


Object Types

An object type is a kind of datatype. You can use it in the same ways that you use more familiar datatypes such as NUMBER or VARCHAR2. For example, you can specify an object type as the datatype of a column in a relational table, and you can declare variables of an object type. You use a variable of an object type to contain a value of that object type. A value of an object type is an instance of that type. An object instance is also called an object. Example 1-1 shows how to create an object type named person_typ. In the example, an object specification and object body are defined. For information on the CREATE TYPE SQL statement, see Oracle Database SQL Reference. For information on the CREATE TYPE BODY SQL statement, see Oracle Database SQL Reference.

Example 1-1 Creating the person_typ Object

CREATE TYPE person_typ AS OBJECT (
  idno           NUMBER,
  first_name     VARCHAR2(20),
  last_name      VARCHAR2(25),
  email          VARCHAR2(25),
  phone          VARCHAR2(20),
  MAP MEMBER FUNCTION get_idno RETURN NUMBER, 
  MEMBER PROCEDURE display_details ( SELF IN OUT NOCOPY person_typ ));
/

CREATE TYPE BODY person_typ AS
  MAP MEMBER FUNCTION get_idno RETURN NUMBER IS
  BEGIN
    RETURN idno;
  END;
  MEMBER PROCEDURE display_details ( SELF IN OUT NOCOPY person_typ ) IS
  BEGIN
    -- use the PUT_LINE procedure of the DBMS_OUTPUT package to display details
    DBMS_OUTPUT.PUT_LINE(TO_CHAR(idno) || ' ' || first_name || ' ' || last_name);
    DBMS_OUTPUT.PUT_LINE(email || ' '  || phone);
  END;
END;
/

Object types have some important differences from the more familiar datatypes that are native to a relational database:

  • A set of object types does not come ready-made with the database. Instead, you define the specific object types you want by extending built-in types with user-defined ones as shown in Example 1-1.

  • Object types are composed of parts, called attributes and methods, illustrated in Figure 1-2.

    • Attributes hold the data about an object's features of interest. For example, a student object type might have name, major, and graduation date attributes. An attribute has a declared datatype which can in turn be another object type. Taken together, the attributes of an object instance contain that object's data.

    • Methods are procedures or functions provided to enable applications to perform useful operations on the attributes of the object type. Methods are an optional element of an object type. They define the behavior of objects of that type and determine what (if anything) that type of object can do.

Figure 1-2 Object Attributes and Methods

Description of adobj035.gif follows


Object types are less generic than native datatypes. In fact, this is one of their major virtues. You can define object types to model the actual structure of the real-world entities, such as customers and purchase orders, that application programs deal with. This can make it easier and more intuitive to manage the data for these entities. In this respect object types are like Java and C++ classes.

You can think of an object type as a blueprint or template which defines structure and behavior. An instantiation of the object type creates an object built according to the template. Object types are database schema objects, subject to the same kinds of administrative control as other schema objects.

You can use object types to model the actual structure of real-world objects. Object types enable you to capture the structural interrelationships of objects and their attributes instead of flattening this structure into a two-dimensional, purely relational schema of tables and columns. With object types you can store related pieces of data in a unit along with the behaviors defined for that data. Application code can then retrieve and manipulate these units as objects. See Chapter 6, "Managing Oracle Objects".

Objects

When you create a variable of an object type, you create an instance of the type and the result is an object. An object has the attributes and methods defined for its type. Because an object instance is a concrete thing, you can assign values to its attributes and call its methods.

You use the CREATE TYPE statement to define object types. In Example 1-1, the CREATE TYPE statement define the object type person_typ.

The indented elements idno, name, and phone in the CREATE TYPE statements are attributes. Each has a datatype declared for it. These are simplified examples and do not show how to specify member methods.

Defining an object type does not allocate any storage. After they are defined, object types can be used in SQL statements in most of the same places you can use types like NUMBER or VARCHAR2.

For example, you might define a relational table to keep track of your contacts, as shown in Example 1-2.

Example 1-2 Creating the contacts Table with an Object Type Column

CREATE TABLE contacts (
  contact         person_typ,
  contact_date    DATE );

INSERT INTO contacts VALUES (
  person_typ (65, 'Verna', 'Mills', 'vmills@oracle.com', '1-800-555-4412'), 
 '24 Jun 2003' );

The contacts table is a relational table with an object type as the datatype of one of its columns. Objects that occupy columns of relational tables are called column objects. See "Row Objects and Column Objects".

Object Methods

Methods are functions or procedures that you can declare in an object type definition to implement behavior that you want objects of that type to perform. For example, a method is declared in Example 1-1 to allow comparisons between person_typ objects.

The general kinds of methods that can be declared in a type definition are:

  • Member

  • Static

  • Constructor

A principal use of methods is to provide access to the data of an object. You can define methods for operations that an application is likely to want to perform on the data so that the application does not have to code these operations itself. To perform the operation, an application calls the appropriate method on the appropriate object.

In Example 1-3, the SQL statement uses the get_idno() method to display the Id number of persons in the contacts table:

Example 1-3 Using the get_idno Object Method

SELECT c.contact.get_idno() FROM contacts c;

You can also define static methods to compare object instances and to perform operations that do not use any particular object's data but instead are global to an object type.

A constructor method is implicitly defined for every object type, unless this default constructor is over-written with a user-defined constructor. A constructor method is called on a type to construct or create an object instance of the type. See "Object Methods".

Type Inheritance

Type inheritance adds to the usefulness of objects by enabling you to create type hierarchies by defining successive levels of increasingly specialized subtypes that derive from a common ancestor object type, which is called a supertype of the derived types. Derived subtypes inherit the features of the parent object type but extend the parent type definition. The specialized types can add new attributes or methods, or redefine methods inherited from the parent. The resulting type hierarchy provides a higher level of abstraction for managing the complexity of an application model.

For example, specialized types of persons, such as a student type or a part-time student type with additional attributes or methods, might be derived from a general person object type. See "Inheritance in SQL Object Types".

Type Evolution

Using an ALTER TYPE statement, you can modify, or evolve, an existing object type to make the following changes:

  • Add and drop attributes

  • Add and drop methods

  • Modify a numeric attribute to increase its length, precision, or scale

  • Modify a varying length character attribute to increase its length

  • Change a type's FINAL and INSTANTIABLE properties

Dependencies of a type to be altered are checked using essentially the same validations applied for a CREATE TYPE statement. If a type or any of its dependent types fails the type validations, the ALTER TYPE statement rolls back.

Metadata for all tables and columns that use an altered type are updated for the new type definition so that data can be stored in them in the new format. Existing data can be converted to the new format either all at once or piecemeal, as it is updated. In either case, data is always presented in the new type definition even if it is still stored in the format of the older one.

Object Tables

An object table is a special kind of table in which each row represents an object. In Example 1-4 the statement creates an object table for person_typ objects.

Example 1-4 Creating the person_obj_table Object Table

CREATE TABLE person_obj_table OF person_typ;

You can view this table in two ways:

  • As a single-column table in which each row is a person_typ object, allowing you to perform object-oriented operations

  • As a multi-column table in which each attribute of the object type person_typ; such as idno, name, and phone; occupies a column, allowing you to perform relational operations

Example 1-5 illustrates several operations on an object table.

Example 1-5 Operations on the person_obj_table Object Table

INSERT INTO person_obj_table VALUES (
       person_typ(101, 'John', 'Smith', 'jsmith@oracle.com', '1-800-555-1212') );

SELECT VALUE(p) FROM person_obj_table p
        WHERE p.last_name = 'Smith';

DECLARE
  person person_typ;
BEGIN -- PL/SQL block for selecting a person and displaying details
  SELECT VALUE(p) INTO person FROM person_obj_table p WHERE p.idno = 101;
  person.display_details();
END;
/

The first SQL statement in Example 1-5 inserts a person_typ object into person_obj_table, treating person_table as a multi-column table. The second SQL statement selects from person_obj_table as a single-column table, using the VALUE function to return rows as object instances. See "VALUE" for information on the VALUE function.

The PL/SQL block in Example 1-5 selects a specific person and executes a member function of person_typ to display details about the specified person. For more information on the use of PL/SQL with objects, see Oracle Database PL/SQL User's Guide and Reference.

By default, every row object in an object table has an associated logical object identifier (OID) that uniquely identifies it in an object table. In a distributed and replicated environment, the system-generated unique identifier lets Oracle identify objects unambiguously. See "Storage Considerations for Object Identifiers (OIDs)" for information on Object Identifiers and using REFs to OIDs.

Row Objects and Column Objects

Objects that are stored in complete rows in object tables are called row objects. Objects that are stored as columns of a table in a larger row, or are attributes of other objects, are called column objects.

Object Views

An object view is a way to access relational data using object-relational features. It lets you develop object-oriented applications without changing the underlying relational schema.

Oracle allows the creation of an object abstraction over existing relational data through the object view mechanism. You access objects that belong to an object view in the same way that you access row objects in an object table. Oracle also supports materialized view objects of user-defined types from data stored in relational schemas and tables. By using object views, you can develop object-oriented applications without having to modify existing relational database schemas.

Object views also let you exploit the polymorphism that a type hierarchy makes possible. A polymorphic expression can take a value of the expression's declared type or any of that type's subtypes. If you construct a hierarchy of object views that mirrors some or all of the structure of a type hierarchy, you can query any view in the hierarchy to access data at just the level of specialization you are interested in. If you query an object view that has subviews, you can get back polymorphic data—rows for both the type of the view and for its subtypes. See Chapter 5, "Applying an Object Model to Relational Data".

References

A REF is a logical pointer to a row object that is constructed from the object identifier (OID) of the referenced object and is an Oracle built-in datatype. REFs and collections of REFs model associations among objects, particularly many-to-one relationships, thus reducing the need for foreign keys. REFs provide an easy mechanism for navigating between objects. You can use the dot notation to follow the pointers. Oracle does joins for you when needed, and in some cases can avoid doing joins.

You can use a REF to examine or update the object it refers to. You can also use a REF to obtain the object it refers to. You can change a REF so that it points to a different object of the same object type hierarchy or assign it a null value.

Example 1-6 illustrates a simple use of a REF.

Example 1-6 Using a REF to the emp_person_typ Object

CREATE TYPE emp_person_typ AS OBJECT (
  name     VARCHAR2(30),
  manager  REF emp_person_typ );
/
CREATE TABLE emp_person_obj_table OF emp_person_typ;

INSERT INTO emp_person_obj_table VALUES (
   emp_person_typ ('John Smith', NULL));
   
INSERT INTO emp_person_obj_table
  SELECT emp_person_typ ('Bob Jones', REF(e))
    FROM emp_person_obj_table e
    WHERE e.name = 'John Smith';

See "Rules for REF Columns and Attributes" and "Design Considerations for REFs".

Scoped REFs

In declaring a column type, collection element, or object type attribute to be a REF, you can constrain it to contain only references to a specified object table. Such a REF is called a scoped REF. Scoped REF types require less storage space and allow more efficient access than unscoped REF types.

Example 1-7 shows REF column contact_ref scoped to person_obj_table which is an object table of type person_typ.

Example 1-7 Creating the contacts_ref Table Using a Scoped REF

CREATE TABLE contacts_ref (
  contact_ref   REF person_typ SCOPE IS person_obj_table,
  contact_date  DATE );

To insert a row in the table, you could issue the following:

INSERT INTO contacts_ref
  SELECT REF(p), '26 Jun 2003'
    FROM person_obj_table p
    WHERE p.idno = 101;

A REF can be scoped to an object table of the declared type (person_typ in the example) or of any subtype of the declared type. If scoped to an object table of a subtype, the REF column is effectively constrained to hold references only to instances of the subtype (and its subtypes, if any) in the table. See "Inheritance in SQL Object Types".

Dangling REFs

It is possible for the object identified by a REF to become unavailable through either deletion of the object or a revoking of privileges. Such a REF is called dangling. Oracle SQL provides a predicate (called IS DANGLING) to allow testing REFs for this condition.

Dangling REFs can be avoided by defining referential integrity constraints. See "Rules for REF Columns and Attributes".

Dereferencing REFs

Accessing the object referred to by a REF is called dereferencing the REF. Oracle provides the DEREF operator to do this. Dereferencing a dangling REF returns a null object, as shown in Example 1-8.

Example 1-8 Using DEREF to Dereference a REF

SELECT DEREF(c.contact_ref), c.contact_date FROM contacts_ref c;

Oracle also provides implicit dereferencing of REFs. For example, to access the manager's name for an employee, you can use a SQL expression similar to the following:

SELECT e.name, e.manager.name FROM emp_person_obj_table e
  WHERE e.name = 'Bob Jones';

In the example, e.manager.name follows the pointer from the person's manager, and retrieves the manager's name. Following the REF like this is allowed in SQL, but not in PL/SQL.

Obtaining REFs

You can obtain a REF to a row object by selecting the object from its object table and applying the REF operator. You can obtain a REF to the person with idno equal to 1 as shown in Example 1-9.

Example 1-9 Obtaining a REF to a Row Object

DECLARE 
  person_ref REF person_typ;
BEGIN 
  SELECT REF(p) INTO person_ref
    FROM person_obj_table p 
    WHERE p.idno = 101;    
END;/

The query must return exactly one row. See "Storage Size of REFs".

Collections

For modeling multi-valued attributes and many to many relationships, Oracle supports two collection datatypes: varrays and nested tables. Collection types can be used anywhere other datatypes can be used. You can have object attributes of a collection type in addition to columns of a collection type. For example, you might give a purchase order object type a nested table attribute to hold the collection of line items for a given purchase order.

You use the CREATE TYPE statement to define collection types. In Example 1-10, the CREATE TYPE statements define the object types people_typ and dept_persons_typ.

Example 1-10 Creating the people_typ Collection Datatype

CREATE TYPE people_typ AS TABLE OF person_typ;
/

CREATE TYPE dept_persons_typ AS OBJECT (
  dept_no    CHAR(5),
  dept_name  CHAR(20),
  dept_mgr   person_typ,
  dept_emps  people_typ);
/

In this simplified example, people_typ is a collection type, specifically a nested table type. The dept_persons_typ object type has an attribute people_typ of this type. Each row in the people_typ nested table is an object of type person_typ which was defined in Example 1-1. See "Creating Collection Datatypes".

Language Binding Features

This section lists the key features of the object-relational model that are related to languages and application programming interfaces (APIs).

SQL Object Extensions

To support the new object-related features, SQL extensions, including new DDL, have been added to create, alter, or drop object types; to store object types in tables; and to create, alter, or drop object views. There are DML and query extensions to support object types, references, and collections. See"SQL".

PL/SQL Object Extensions

PL/SQL is an Oracle database programming language that is tightly integrated with SQL. With the addition of object types and other SQL types, PL/SQL has been enhanced to operate on object types seamlessly. Thus, application developers can use PL/SQL to implement logic and operations on user-defined types that execute in the database server. See "PL/SQL".

Java Support for Oracle Objects

Oracle Java VM is tightly integrated with the RDBMS and supports access to Oracle Objects through object extensions to Java Database Connectivity (JDBC), which provides dynamic SQL, and SQLJ, which provides static SQL. Thus, application developers can use the Java to implement logic and operations on object types that execute in the database server. With Oracle, you can now also create SQL types mapped to existing Java classes to provide persistent storage for Java objects using SQLJ object types where all the methods are implemented in their corresponding Java classes. See "Java Object Storage".

External Procedures

Database functions, procedures, or member methods of an object type can be implemented in PL/SQL, Java, or C as external procedures. External procedures are best suited for tasks that are more quickly or easily done in a low-level language such as C, which is more efficient at machine-precision calculation. External procedures are always run in a safe mode outside the address space of the RDBMS server. Generic external procedures can be written that declare one or more parameters to be of a system-defined generic type. The generic type permits a procedure that uses it to work with data of any built-in or user-defined type.

Object Type Translator/JPublisher

Object Type Translator (OTT) and Oracle JPublisher provide client-side mappings to object type schemas by using schema information from the Oracle data dictionary to generate header files containing Java classes and C structures and indicators. These generated header files can be used in host-language applications for transparent access to database objects.

Client-Side Cache

Oracle provides an object cache for efficient access to persistent objects stored in the database. Copies of objects can be brought into the object cache. Once the data has been cached in the client, the application can traverse through these at memory speed. Any changes made to objects in the cache can be committed to the database by using the object extensions to Oracle® Call Interface programmatic interfaces.

Oracle Call Interface and Oracle C++ Call Interface

Oracle Call Interface (OCI) and Oracle C++ Call Interface provide a comprehensive application programming interface for application and tool developers seeking to use the object capabilities of Oracle. Oracle Call Interface provides a run-time environment with functions to connect to an Oracle server, and control transactions that access objects in the server. It allows application developers to access and manipulate objects and their attributes in the client-side object cache either navigationally, by traversing a graph of inter-connected objects, or associatively by specifying the nature of the data through declarative SQL DML. Oracle Call Interface also provides a number of functions for accessing metadata information at run-time about object types defined in the server. Such a set of functions facilitates dynamic access to the object metadata and the actual object data stored in the database. See "Oracle Call Interface (OCI)" and "Oracle C++ Call Interface (OCCI)".

Pro*C/C++ Object Extensions

The Oracle Pro*C™ precompiler provides an embedded SQL application programming interface and offers a higher level of abstraction than Oracle Call Interface. Like Oracle Call Interface, the Pro*C precompiler allows application developers to use the Oracle client-side object cache and the Object Type Translator Utility. Pro*C supports the use of C bind variables for Oracle object types. Furthermore, Pro*C provides new simplified syntax to allocate and free objects of SQL types and access them by either SQL DML, or through the navigational interface. Thus, it provides application developers many benefits, including compile-time type checking of (client-side) bind variables against the schema in the server, automatic mapping of object data in an Oracle server to program bind variables in the client, and simple ways to manage and manipulate database objects in the client process. See "Oracle Call Interface (OCI)".

OO4O Object Extensions

Oracle Objects For OLE (OO4O) is a set of COM Automation interfaces/objects for connecting to Oracle database servers, executing queries and managing the results. Automation interfaces in OO4O provide easy and efficient access to Oracle features and can be used from virtually any programming or scripting language that supports the Microsoft COM Automation technology. This includes Visual Basic, Visual C++, VBA in Excel, VBScript and JavaScript in IIS Active Server Pages. See "Oracle Objects For OLE (OO4O)".

PKNU`¨PKpUIOEBPS/adobj034.gif ~GIF89ak???@@@///OOOooo___ppp А000```PPP!,kdihl'tmx|pH,w`l:ШtJZqzసzn8:;~Xrt{>}o^nvAĎɫғ֑Zۉj  r kff3@?J8P^#@@ЌC :nֹ_ɀS F@Y3=9b55x!5] |=$R=h(M8KvxIœ$bpX⊆&#(c.ތ8Ędȣ5>i$5)HG6JäTڐdϨX<\ Zr)fE_heؤfI\!t)o) |) 1i[H0C.*DX N;tjf*)4bꫬ )"j˭+밮K챢첖(ݤ &J;dv+vD8K+kZnna,l'+p>< ClePl11k$x$+<&K*8-| 1#225 9GL~6&@=ΡtP K?Ҵ5|KDjuT5$[sj2L`AU_]?C ׶tPc׀5݁m52>F~6޵6h)H[qzv˹+WAh( 8WcWS4 zC@ 4^g=N>#zӛ1hh쭈Z~ϝj D@i*9O]ŀx?Vxr%y ،C :u/ s:= +@0 A$r 栆E'3C5g` rHLb2D1ay䡻ϼ.~I>%,A:hH!V:΋$pe*hh םzS>A AA>39Đ c75юw!<#;n|F, hbs'C(wU6k`c%u՜_DEŏ06Ngc01Ps԰)R ]B 0 }tC:0w֐L8|Rd.iIs%( zP9$TlbC QtlxhEqQs,GߠQޢ# ">M *+e*\Ғʴ"}i.czPt6(ŰHeÄ9:P}#Oj l)@mTXs&ֱRK*Y%X Z+6U c|Xq5cIhMlcUf3[rVEҚ m4p;MR+RFn @ڡl-mW UhoQv\A7 Fs4We `uw W3@oz;\d0+w1d{)wwy[[[.8 ~2_ 'n Na!f[`DXP7.Έg̊ˀ(q+L|$$@JK^RB܀+!@AHRА| $?Ont,' a怫́簝0 ;PKK PKpUIOEBPS/adobj001.gif1yGIF89af ???@@@Р000ooo```///___OOO pppPPP! ,f@pH,Ȥrl:ШtJZجvzxL.z.||N ~nv]SrRԷBިqIz W@cHaR !49p32ِ $ Qxx`%  \ri\t)]0R$$@HATH0A@ kQM]l߆ 0BҒzPA`4$ႀ ^)6`& iKz]* ,RR*0PX#[vW h5K Yμ3/U@S0/$PXAY+һ^%c03`:% "Y] !Qz reAt~?v`@UU/^OD J( (*Jϯs+\ qk?r +l7O+mI_WE \9.CHxPq+B q1BP^ mg,{a_&P  0D[.z` H2T£*MFdXQ>QU_Հ 0hc؄9>wbCbquk"I;u,eؠB(L&PLBK@e0- =0ALKz=PW1.ҔGYAz$4 @ĒŞdAX>d< .@[:@ -*Oz/D%9Hl2@D& .i)@23d:%B(d8E 碒)GjԄ$LtUsETxի5mSI%*fBPZJa(Z |3(L p*T8[}L*@%h!u !cam)PI$E h@,+b&\Kʵ)B7B;E P`u EަΧ拊榱ezׂ=:CNpRD/W{ 6{ F7h餚X # nlj;DtcG=$o8 =qooXcpG"*[XNÔJ_v6V,ew-`>b -9 f'a>N"#ށz. w]qR[,L $DA?ga@bGSZ (wEX C CH?$ZXt;Zp( ]86pe?wl$ၝ2 a_ҝh_ Yc/8 sC˝o fvNaxzY:!\c歜4nYRulzoU@{fg A(mYs[S) `ޢp(7F"G)Edl1{63aYIgnOtF,$C)MFbw,@vE'tsc@]`sU(aOK PD&D.)e-1}Y+z XtZ Y'ֵsj7O @q쑗%nn Wֻ,!cmimݶx`X>9M#soمly];Џo_/pOO+}9fq8X8UgvCAMw*g$ D[/}0ck'_q >5(`|/6Wtf;W&bpiEQ]]"ƀHD:hHL\* +0daS-8(Q@vܷA~v%VpVi]'P c5H}7xefAP*ALq3Wrvddnf8B7#kEGlNPtT&`h'S{8FKW81(*w}h}(HQ3`)yl$ F{tx?WEW8p8WhuWy~8H~GShLȏa}#D ;HHh IsÍH y s8>Өguzv ƌ0 8(L yBsc=ɓ/VH_bOqf87: ֔+:H_1W> 8el&ؕ-DoRXoŖǨfRt0Ad1t\i&ZlVdr B+4SDA%1@JY{ )!q((&",Y9)uJj12_d0lQgl5y`l89x:zzgp|jDr`O(p_UjReywb`aCjOђez2TprS7yZZ  Z*sy}ỹ"c  ?Y>yF0a"Vz,R1"2G#` p 6Щ`P`Y `u(W(xXF j A2&[ Ppb1sЁ:AYdXE` Z3.GY3Sr$tPtI SPyPʯ;sްSԂl)t P#m:XI`Tf,WV|Ua1H0LଦJ W"SE]ѷAbLԐOݚQʸFxˉQDR`rw4!jop{)z0E0 +蛦j;nN1![ Kp۽4;@zˢ**  r0PsH!0WxMR7㴗Ć"11yEu6Yb CH}òz Qj[ BL1YǤ+"'%TXL9TVoL| * jp@T<yв`jzUJCe3`L,e=L!6!X(%%' ỻr$[&T@Z  ErrVYg1.ZfTdkk^V!M /'o2]LE`!<o$Ao@TTViم3W/ T-ʗ6 b8JW3Yl2Y3ڨ6A]Sdl;aliP] @1Kf7{ H0M\-m՟I^MR#jm&a!W&Fo x`z OH0ku;iyPZJux5xF5jE,{M" ]VoKϛ8ٌLNY'wC<_܈W07tANPi AUEj7mo= El,zOD1x}?F2ZӬ*hKȉ[ 8v*9\ "b_lI_H@.oD}m gy,nEA!Y- !oB(!'N2leUo&WE\ !5^ F@D RT g0 E(E\>Q@Ba8@)([eTN@v%М^y@4  <0.?*:7?6$RP>,rz>`<<2 < )%;(1 >, s@a3, |e#AU˗1OH,Hos0LriӧQ ̯aYb<,A@o߿>xqǑ`kϡzuױg׾{ள@yѧW}{Ï>׿ ?CLPA$!|>[ 19pB+H,QDϹ YhaLCxKNyGd`$ŹM7&"|+dB& LS +@d ,3Sʺs/ 4 ɜC$0)H JE ((hL" <)Yx2!LU@ ӃḄ4 .Er.  cx* !U]V]κia ):PJ+0w|9ܰw3󅁸L1J$xE>т7t! P=ʓ+Ȁ`X,{AtaånxXC#dlP9Pr\%B@lUN&hFmȄRm|IP $Kи8@f&`a4^Q&JiQBwx Cw@ݬj&Mf$w|o!ym{`OcRa5(:a-VhّI[Jpʸ)|AaO |0$_b!<`кŮJadz$n&%z(f>8@ 5 N20#p&'N*0%ML~pdl1L2vp g؏ `2 2 $cHe$)\nű< ˫4TYd͜<+B<6͟!ꜪO <ϗ"5p#fЍXڸC }%}ҟӣ9.!EHUՓYCY+ Yw-YAWML(-ISL_mV8_˓2BFJNRVZ^bfbnz~!- <4PR$ ,cJ%F]|,37;?C/D3{Tc3 dw{(P< *"d(wOOS((L+,3L|\O`/_| &  L[v eǎA1I 4B $ AJ<(i!A %=PU O =@0Mrb'J&Z\xy'UA[Qpu;/8UwaȪx1J)3bP`IH 0v*el~jBp3XPKk6 𪲀hفSVӚ]s @غ-6 `u)d584`ع6rhδMKL2<2Hfph+X n *>UhY 223$[_*lTpcJPO_J[PS]P[[tc]uv\]m7*I]o۝ЁSdbF{BC xxСmQ~jdw.q#@6-3P @-ٯ-+۽^uT0|ƫpkĞx@)h5 S_w`]?<Ted~^d-/`caL<+ p*bޢ'7wK{ ɡ("Y<[șFF.ހ*¸ {(@n6h"J\"" A;PKC11PKpUIOEBPS/adobj008.gifWGIF89axDDDͿ[[[KKK???***ҵɰչyyy```"""}}}ttt 444qqqlllټiiiUUUeeeQQQ999!?,xH@-z(\ȰÇ#JHŋ3jȱǏ Cx(S\9 ȜI͛8sɳϟ@ JѣH*ą,JRXjʵׯ`ÊKٳhӪ]˶۷dԻx V˷߿ L ?˘KÐ#KLe{(nyˠCM̛;6ٴװcz[ͻoٵqxa,"1 6D 9 2CSr[3NHzf3P-@ \%@( ` $` .tBP t_'`} i  XmB1 vHY5@ ]wY-Bd`` 4 Ђ(4A$  =y+<@'C'hǕ5,T w~WeЃ8d@q!0 y$kXk ¤=` hy=b$D 2胏(a0PC  i @C!_#jpB @h-Fj%eu 9B54[CqGp($I@VPV,p%=HPA/@h@**Dn ܰg('  `@WPW @5<C `(*P(p <( $IdhZ .0U\-7C_PC%d.> @BP42 &%jPB i |ñ lB𮛪  \ABKU0hP@xABh \  "PAv"E4 R 0tɫI V`B}>p} bLIBtFЃ nPJJ:*Z!|p` @6g>kAʁMrA'&0+0 $B#Rћ$0gB4>}]<$+3p@ +q; 0'{R)!H!TC J-@W23éP}4 o>MD )9ruI !<& vlJqjPJy7ΉbJA[*N4'( ʖ-8`:h@Jx6> K x wxtiiS%:-P97pI1$x>dr]ͮ I)QJV7 h U e@ f)xC$nVkv$H@PpT49W(5ԿP3$9γe:H<]DFe0~ #VH\ tEVB-7@ȮNvW]PձK ` uK%i$@ ;Wif{[@n3 p@Wf|{>U} h U t=UE*Z mf@RT RaVYEk7s*KaϖoG-25|0AH;n 1"$l j}ZrVNts \:|y[R ^KyBmx >- Љ W:$jiw 6pAKӮ @ NQ+|H>zt]D0Zရ4$ɺ$( (4SX 0"`$ع*@MF|%ժg^kceŜUD`_d6F]0:v"T/,P/ ̇;) L30` 0X-PVإ `d`10 " 9p@P_d~l jDgց@H,@#06;p7)sP0UZ~ JP7u=(&0T,pq~"`~ t/,`ɒ<c$ CvpI|A*F@$PaWx7xm:*@@ c^2[>@+PRψ,A Sp!x~YS2I&`@O/Qd_-WaR2 i\'p3 2`Bd!EG^um[}+P8P&ikw15~ P{XH!2L>hu&pl#,b yX5Y4%jO5(.P@3nᕃEpgj8 )FW(@>2 48[Z:~607 x5P%7t"@DQѵ*_h-HD%#."S`2/%+H bZREDWy.;*PՉpڙf,7 / O7"6 I"&,2@DW2w5ZA mz*X7ȊzaFMyiR^!Lq'J4#f+qf < %R=f$PIpP4 F9LG"!P.PkѤY=/SzhpiV2(0"nS#%Iėe+P4J~8,s 9`f2@-&S 8`' 5 jN 0*`aRWg! ~-@*ĪCqC@i (o£D `2&PW!pP5Х"` Z T^S(ڛ;7=:%t^ ۰K/OFי>P.K!{+0& ْH&C- 701!Z˫ oq%$'?0p`4&T U%qf9)ʌǪGժ2@P0U&P{` Pn;2 !#0s=}XQFщ -b Zc`g42 xX!xqJ`XGB'UfJ&@=0*@"p @%ɻ%!gy@1pz$]dC{s*.80<2\`=ky ̙ԗ,O,p ˉ.9 8@m 3@&P2! @$Z{`~c;#I0Y 0Л<w@`nZ}.pЙzsIZ|q=̩~e5P*;KI컾 Pd;IU1te'\1%09ʦad\αC3ws3h7y3PݑR$i,0Xa5^NpE2kσP, Vs`%CLJY%wz%9 &  =)LEi Z;+̌;YW3Y;;@= ’0/p/`d~ZQ" (v=a(BWƭN,؅ x*#[_ -6gXϬjl8ْ٨aCځafڑڧڢڀe(یHۢh3(cۋۡ!~dh܊ܠGܒMӚ(ݛH!9 }#1]}| ͊]ڝܭ} ݦ9<،mƎ-ͅ]gL=> N.g7P z   @ԡgS5ՃXAؙu\ Z~=0W6`Q7 ^ 7~zPP^ ~"*{'6~qd3pۀ[:A yDawl(rJ) нuJH2itb7@:4$0 TmB'0mLP\8ruuqNT'ȄD3`ڒ*UkiΆc & nB'(4ӽ'VA:wkcA>^},G礁[+Ŏ} 0&d;(8`[p){ y96@"@+(ZXbs '^৐X'Y##P~ _`l4*pnLR#:&PBx.s<>+1WOVK7STM,ֳ#I"EK2P/l7@$$нV[߽ B& 4X]qPe3UyV1pIP,\.PH(/(};MR>]6,2ZM9OߖH?EM HYi" $&  :dC7(`آZ!E1(DRJ j,@q 1b  @"Ɔ tXGB]Rt8X (ZT1C? ;$ҀA`  hs”06 gD 08d@3jw<C<2"8D/z@C@|$D`J/QQC!/eL5ZrM7M9K L;;4ӡ JX(AnX2PDa DAGa 60R{Ȇf8@Gh@T4 R~AS8mVG"HS'0 S`ⲛ@X r͇`B.``J2(nG1p7 2a}X0"@|P o3X!xp(RiETRO5  oXjA3DP Z \ X`$jJ݋`)(n x OE0A,R`s3ll(, @zXh p S T4+-V D(M,"X`:d= Z 𺁪Hۄ > N0J.0H!<ڗNa ^8>z 0HX!@4p *'_`:   $@*@ 7dl(Ѓ`)yH Я@|$0D/@ 9 ,k f.pLh(PPhXL`P+@P/0 Gb#bƐp$>HT%; ! vܥSs|0  0x= 2p@^0 >P @e^ǩ`[ @'X!0d! |:@s !3((y ? PAI//qX<sY"qh'q .` 2X (A]ɖ Ԁ+ AHTP.9$)q焚?8T|@.@  PL'xV3F`1.5mH@` xI %7`-+(⩆x rX]ɉ"G@LK0JV``" }I9/P@ < 9@(= "a`3A z PL(`Nu!0@ @2 '$, #%-dŢv3! NFv!!Z' < 2@h !@ z`*$ 0U)0@;ͨfi b@yk@M](@NՆ TT$V=kt,P@;=pH,\a:S.Ё փX9C"`@*HeIYuN?pwJmmo iAj. Dg$^= Ԡ . `v A OׅU"F &  P`*͋bjl AQᲂzǴˀ}\`z̎ Bb@:DAv ++1p@d038x `7A | g`:3B^KZ//9L@Ȥh Y >Gϋ! 8(e K<$H W,~6$}P0P 4 7l͌pL5E`P`={ XG)e @5 miG=h\ @38APS/1FP.qhȭd1>dE*8`9`28@rx+Z $.rx4ye ;rȈ!0 ,z\|`JBF(fS4@P#@S4': Zx UC!@wȮ0z ;)[)› [1 ؀ x H 8F ؀I P Pj7wA&{qHa h]GK_ 8<( Z>Q(hoqW iЙeB2ēh?xoPT4?؋d.=FC#ی N; 9))x6I?z9Y(:  sP|6"-\zT @J[ 9NGҐ5-GKH&1G2Dž܌-Hh@B6ᾌHɒlH<ȅd1r9!ɘHL )|lI<5ɟx zI TJ/ ʦ|,ʱYɁLJ "yʭ<J89JL 4KʴL K1JH<ːY˻|Kh$4DTdtDŽȔɤʴĀ{˱K1Ѵ]4/̷7D4 YͰlM7yM Mͩ5ͻEP"΢,N59NLl ԴNyΛ3N4O Δ BP1δ l.O$ʾtK&Ypc4O}~"aPtN ]O47@MHD$ ѭ,Qթ/JQmh2 ڼQQ G p3zLLR\lR'u(A)RR0e1] bQl|S8h/S TT0-;T/IԦ\lT'}Ԟ+TTTT$T U0*U$p/PwӕhվhU0z]`^ucEV$ְdugej֨DcnVVo%rlÀHsvuwxyz{|}~؀؁8tMWit؇؈؉؊؋eLM؏ِّ%ْXؔUٕJ 8٘EǘٚٔuٛYٟٝZ٠%٢EڤEڡUڦuڨڕeکZŀګڭMɪZگ۱%ۦ ۳U۵e e[M[eۻۼ۽۾ۿ%ۼE(ZTDž\ȍۛuȵɵ\ܚ%Х5eݕEݘUׅ֕إų]U] %5EUeh\H }[յ^Z^%UZ5U_Eu]߾]_;_ň$%6FV^8Kv% ` z`Emf5NQva< `ua< #N F(J%&!6"j.bb!^b/6cb f->7V4ub 00Eɔq 8IdHicJd0[t+ `daYXJ@Ȇx yIeF -` XmR LӊUȨt`1꣈PH `eXo4?[(P X@ m 9^c"ncc @2hh$1ZH>K ,Ѐ398i"+R"L@jhf4 (!&<bi (j@0 D ,P 1yJsXu0& _h0V&bb*賹a{h l @h&JhD@a>3a$iЀ3fn$̫k 0eh@j  !ixϳNlp 00f.8 8PCHm*3rk| pl !aB.sz8 (nm?(o8c31ach8I.8 |NhB豀"h3ߪx2V@:Hfn؀" kAI0>IyϹ*1  +BLrov:@?i `kx^p8k؋IqeQm[>/Wh"͓zꁛ L W b7b=u'7 %)"=Ѐ "uhpmX;"j 3(sL4_vih;9p. ~o2(o.dGo. ЁLW2hnx̻Pp oPp!P @1$S3uk' xHpv:V./0#ұ)ehwm B 7=ww)ikr%xҘsx8Q @1z.c! 1j4x2Ñ i PyM0_8P 1Vp)(rPW4@ *zpyIl8uzȞc㱌8hh"B ҉x{؀L xJ)>nL聂B >b&H@-^p 4$ #IA>!dž=dyH 6R|a'.WÞN0aa= ! A ѰD#|44M4ᰃ8 P#Dc=oÁI`PPsMEPD BG ગ>"‡/n8ʁ1|SB8a0l3bAC.zP":"@B H L.'Ca 6԰  2pM }0@ ,DP:t5ݔN^YЃN7@ MyPU0} TII`V!(Q8 0 ,>Tp_}p %  $DNk(p ,Ѓ DVBvjkvRC x)T$rz)57-TwjeݝC'L x7JYII>4`X:hY 4Lf -R'@ fR(Ȅ"OF@w,Ö 0S9\2ə>=9[RPSR'^"(1jЊX<ϴ.n|#(Gv9~# ޱcrE2Lb )I 9|$&3M l9$(Kr3s2!% P!%Y)5@GAFP8, ͇< *]BQ50E `Q HO\/Vc@ i P$ %O{huF}/ԟ-4]pv,Iр 0۝@bP^$xV{µ\{VK jHh 2-:p\ {ZlfAٓ $/APȀ DfP@ i}I, <ծwHw9"JU*Aދ`P `S.!ǻƇi" R&1|'~S؛1(stq88>#d&?8r)E1-s^2 $T> @7}!,9ӹ//ЬyP,_i԰9@Ѻ鳊;ҏ.C%i72Җ4l?8@"0N{Ѡ.0S8APBVzЯo@pX D & p@!t@ ZEX VAl "s!@ P$  H0$yF3Kn _Zdu'G(L F S9s%h+l 0(0  69jLgS֖HD2ZޑLIcbqPf:WǓ `rT d D* 0_ $ TKYAH7ƺx Ox>O/3\f`ky+x8N^DLRv9|yN[V>8y4!) d 8@LN_}=L`ƺ1 A {;$EH |= F_ӷ%_Kd~d)t tV }_%Ry|m@ @dHq)@Tp X%`o-`( FmD `z |n (B؇U P@ !!+5%݀ t0h=<v tQ0@aq≑$=^ $$"R##^^"f(u}"(X& &)&*bwQ"Y,-2S+:+B^,e"$2.#363> @ c(X/r3v7~c4N#525^#e:b%81j::";#H#=U9c#S>c?>@Az?d\#@B>,!DUBPE6d=dFF>:A5$I"EI$5G$LL*UG$MF$"N$6dORN M>HoIP.5SrRRN%FVeHADJeԇqG]%Y&YjVVe[\ \ե"%^W$X9`!a^axvdN&eVe^&fffn&gvg~&h&5vP#U@ kk&lƦl&m֦m&nn&oofkiRB h'r&r.'s6s>'tҦp?-2~vn'wvw~'xx'yyv 0uf{'|Ƨ|VuΧ}'~g]'~e}( \(&.>(eN(V(VZ(fvN~~(u((Ξ((5ƨΨh1((^h(N)()&i\*)6i FiViRf)bvirg )))Ʃ)֩)橞){>YGF'*&.*& I$cNjM <%n*M@`Dbr*j"Eƪj*FIjjn쪪a +T \\@K(Pa @lG (N(+ E$΢ Ľf@xXIvO< 3P,ЈD4̜DMj@8T@dL 4NE`@Ү@vjpD·mk272hTt$2|,ro Q\$y!Et @C$@pD DTWSRIM  4Ŭ,S@DLp@u{_4Z8F|^^5uGC@gOiԀd9g. iE@XS| @CxV @8LEDC C\ T]S( *  (jϐ3ODTzf@4#}d @k B4etPEx$S@ͼX,D[h}WӋX7~oH'  T@5_ sIEI (@@$5 sás|1; Ġlv&ꞀP Ix_݌OHPLNf̳l781CCH;AȄoo .,jrsXJmf L"[Mc7 wkGDuxzC 9TPl6 $@l,f\- D.zI ,@tloO@Cl ^L^Bxxxϑ|@ H抮Pv ;DN<93Ja Ѐ@ <@@шdtDBT9D_Wgz9H#wޖ8ںhyvWtw|Ix,x@E@ X@2@ 4Wx+~?m []E@@^Dh L@t\HD Š`NO8 Vv( D DHj EgZ01d(`0h4LNDSċ`@mǻR9n[yO {V4uŒHIv4:?K<2fdDhJHlI'a@0X0 p Rt^Wč}"dTo^xOH:j@ (@Xnom/nEԀ0\\jbN=@D 'z$L\@P1a>2LTcG\\!zp1@5j(gO?:焉~$UR4qq  |@^ Ȉ@!/d ¾x b#BjHBƉ>.vG( eŇpq㢀T-0E Ԑ122R(U luqg L w&plF 1Z衙C%a $,``/2D8v Ab0a~̀#@&0"X!6`j@;@@8 BH/#z 2HB#z**!lH$ Aǜh08h RL+qJho&h7$#SI8jp)?e-P+=8CAN:YB40,;ߡҗh/AD?$—)u / HȲ, ! @P`<  Fg)E[7h (pP{u[ Hm0xSAH68@SEr[#P@ v 9;x/:j905Fp>HD Hyr$8]F5.ˈTd d P!(GU:d,H ]䖩wE 58A̲@+U2C3E@?<\5}$$@-qV#8\@ VhfPZ<tT@RBV`% @?vЂu )t0hS- @)vǟӄG/2U@9RK`AY|Uh6{ tTj-BL,|9ǁQ+g%Yк,Jۭ~6IkmŖ[lmm fK| 1#k.lup+ w^񎗼5yaP5u{^~}_ܴ` 8XsXr!a OQpAH!6Qb Va OֹŭVt5U5q1z.pL!ȶ=r<%ɫ}E]QYMہ0-)݂$0z: G\WӃ 8a@ x6.'(@nDs.> |s @o@Uou؏"A & T@VᲬ|ۀدJ)^j֥@ :%L"gPApxZYvȨ]s| jZZ{  $kuIa/~(x ` `v 4 ` Th=(a肮 o؎#|lD%w+ePK,0hk nKZLZ^ƈP0 EpN.Z ZD#@0*zZ'f<`'"5#2 xP"=VO-L x@D@ ,0:.b "B, ,bcf8j,P@|h&jl#f \ !Xj<`$jvkj f`b Sl\f@.$$* +PB`Q,"Z@| `fbt6ى'X%"({҉R N "I {`H'$n4@H6`)b hBk.@(bC0IL \`iԦ'J! vetd@@(dh1 :cT j\`B p&ˤZ ȩz8`@fMhb3% D Dq.zDlxbV`@B r@H N28 H. J&&|c O@$r@iN`l@̃,.`IBi`:@%+#bP* @?`D d #] .B 'JkSP}^)r|Jjr,%>Ftv>ю, t ,^AWD%4t&,*`L01e`0$`--" 0@3s  ,"mĩDP5b  H'ryL,"#mxZcV`(w>'H`%ңT`@8kN` N`+,H.cA;18T"ọM+|j>5@rbBrl`2nX,}3WP,,.ZMNH| P &Z5 „cj`T`Jj@?0@DeB B* ۤB$ 46d&;YR^6.` \'4bR qĂ b޼N@6*# 7?H F"T\6N ffj n2@+c$I鴎^4F#a4,BtE)`Cq mh@^ihq/,JI^iGǡDF:B`s b` 61ef`4 *jT V "~"8^9XAe8B6PP*޳1B51al^Z'IX}2ũfbfLHw&@@J"@z`B<`񘔲7 (ct L"ZX L>Jh@>t 9$h^ @Z,%n0 =}4' /d `v E(tkZ@92'z&EhEnD@$ȓl0A̪#AL %X`st  ;eGV⤷WDX e(#JvouU$#^PT6@,(f`0 ?"@]&+ $@#`ee ?V} [lP׺Rsw,lIǼpze Lѻԛ;dF@<| <b9!-1|ώf0=AG tqC̭+Й MIm)>5~U|=7:bIMQ>U~Y]a>e~imq>2KR戜;+u>~艾>y~Nr>~ꩾ;PK;%WWPKpUIOEBPS/img_text/darbbook.css*/* ========================================================================== */ /* darbbook.css */ /* Release 0.0.1 */ /* Last revision 02/07/03 */ /* 2003, Oracle Corporation. All rights reserved. */ /* ========================================================================== */ /* This is not intended to be a stand-along CSS. Instead, it cascades on */ /* top of the BLAF CSS, providing minimal changes to the existing styles */ /* in BLAF, while defining further styles for DARB-specific classes. */ /******************************************************************************/ /* BLAF Overrides/Additions */ /******************************************************************************/ /* First, we need a couple tweaks to the BLAF CSS. */ /* H4 needs to be weight BOLD, as "normal" is too light for accessibility */ H4 { font-weight:bold; } /* BLAF doesn't include styles for H5/H6, so we'll include them. Same */ /* Font family as H1-H4, just slightly smaller and BOLD as well. */ H5, H6 { font-family: Arial, Helvetica, Geneva, sans-serif; color:#336699; background-color : #FFFFFF; } H5 { font-size: 0.9em; font-weight: bold; } H6 { font-size: 0.7em; font-weight: bold; } /* Loose the H1 underscore */ H1 { border-width : 0px 0px 0px 0px; } /* BLAF doesn't provide much contrast between links and visited links */ /* so we'll add a little red to increase contrast. */ A:visited { color : #AA3300; background-color : #FFFFFF; } /******************************************************************************/ /* DARB-specific formats */ /******************************************************************************/ .bold { font-weight: bold; } .italic { font-style: italic; } .bolditalic { font-weight: bold; font-style: italic; } .codeinlinebold { font-weight: bold; } .codeinlineitalic { font-style: italic; } .codeinlineboldital { font-weight: bold; font-style: italic; } .syntaxinlinebold { font-weight: bold; } .syntaxinlineitalic { font-style: italic; } .syntaxinlineboldital { font-weight: bold; font-style: italic; } .bridgehead { font-family: Arial, Helvetica, Geneva, sans-serif; color:#336699; background-color : #FFFFFF; font-weight: bold; } .term, .glossterm { font-weight: bold; } .glossaryterm { font-weight: bold; } .keyword { font-weight: bold; } .variable { font-style: italic; } .msg, .msgexplankw, .msgactionkw { font-weight: bold; } .underline { text-decoration: underline; } .superscript { vertical-align: super; } .subscript { vertical-align: sub; } .listofeft { border: none; } .titleinfigure, .titleinexample, .titleintable, .titleinequation { font-weight: bold; font-style: italic; } .subhead1, .subhead2, .subhead3 { font-family: Arial, Helvetica, Geneva, sans-serif; color: #336699; background-color : #FFFFFF; font-weight: bold; } .subhead1 { font-size:1.1em; } .subhead2 { font-size:1.0em; } .subhead3 { font-size:0.9em; display: inline; } /* When lists are inside tables, they need to be more "compact" so they don't */ /* spread the table out. We need to suppress the natural line break in the */ /* para element for "paras inside a list item inside a table data" */ td li p { display: inline; } TD.copyrightlogo { text-align:center; font-size: xx-small; } SPAN.copyrightlogo { text-align:center; font-size: xx-small; } IMG.copyrightlogo { border-style:none; } p.betadraftsubtitle { text-align:center; font-weight:bold; color:#FF0000; } .betadraft { color:#FF0000; } .comment { color:#008800; } PK*/*PKpUIOEBPS/img_text/blafdoc.cssF/* blafdoc.css */ /* Release 1.1.0 */ /* Copyright 2002, 2003 Oracle. All rights reserved. */ /* ========================================================================== */ BODY { font-family : Arial, Helvetica, Geneva, sans-serif; background-color : #FFFFFF; color : #000000; } BODY, P, TABLE, TD, TH, OL, UL, A, DL, DT, DD, BLOCKQUOTE, CAPTION { font-family : Arial, Helvetica, Geneva, sans-serif; font-size : small; } A:link { color : #663300; background-color : #FFFFFF; } A:active { color:#ff6600; background-color : #FFFFFF; } A:visited { color:#996633; background-color : #FFFFFF; } A.glossary-link { border-bottom : 1px dotted; text-decoration : none; } H1, H2, H3, H4 { font-family: Arial, Helvetica, Geneva, sans-serif; color: #336699; background-color : #FFFFFF; } H1 { font-size : 1.6em; font-weight: bold; border : solid #CCCC99; border-width : 0px 0px 1px 0px; width : 100%; } H2 { font-size:1.3em; font-weight: bold; } H3 { font-size:1.1em; font-weight: bold; } H4 { font-size:1em; font-weight: normal; } H1 A, H2 A, H3 A, H4 A { font-size: 100%; } PRE, CODE { font-family: Courier, "Courier New", monospace; font-size:1em; } CODE { color: #336699; } CODE .code-comment { color: #000000; } H1 A CODE, H2 A CODE, H3 A CODE, H4 A CODE { color: #336699; font-weight: bold; } A:link CODE { color: #663300; } A:active CODE { color: #ff6600; } A:visited CODE { color: #996633; } TABLE { font-size: small; } CAPTION { text-align : center; font-weight : bold; width: auto; } TD { vertical-align : top; } TH { font-weight: bold; text-align: left; vertical-align : bottom; color: #336699; background-color: #FFFFFF; } TABLE.table-border { border : 1px solid #CCCC99; } TABLE.table-border TD, TABLE.table-border TH { padding : 2px 4px 2px 4px; background-color: #FFFFFF; border : 1px solid #CCCC99; } TABLE.table-border TH.table-header-border-left, TABLE.table-border TH.table-header-border-middle, TABLE.table-border TH.table-header-border-right { background-color: #cccc99; color: #336699; } TABLE.table-border TH.table-header-border-left { border-left : 1px solid #CCCC99; border-right : 1px solid #FFFFFF; background-color: #cccc99; } TABLE.table-border TH.table-header-border-middle { border-left : 1px solid #FFFFFF; border-right : 1px solid #FFFFFF; background-color: #cccc99; } TABLE.table-border TH.table-header-border-right { border-left : 1px solid #FFFFFF; border-right : 1px solid #CCCC99; background-color: #cccc99; } SPAN.gui-object { font-weight: bold; } P.horizontal-rule { width : 100%; border : solid #CCCC99; border-width : 0px 0px 1px 0px; margin-bottom : 2em; } div.zz-skip-header { margin-bottom : 0px; margin-top : -2px; padding : 0px; text-align:center; line-height : 1px; } div.zz-skip-header a:link, div.zz-skip-header a:visited, div.zz-skip-header a:active { color:white; background-color:white; text-decoration:none; font-size:.1em; line-height : 1px; } TD.zz-nav-header-cell { text-align : left; font-size : small; width : 99%; color:#000000; background-color : #FFFFFF; font-weight : normal; vertical-align : top; margin-top : 0px; padding-top : 0px; } A.zz-nav-header-link { font-size : small; } TD.zz-nav-button-cell { text-align : center; width : 1%; vertical-align : top; padding-left : 4px; padding-right : 4px; margin-top : 0px; padding-top : 0px; } A.zz-nav-button-link { font-size : x-small; } DIV.zz-nav-footer-menu { width : 100%; text-align : center; margin-top : 1em; margin-bottom : 2em; } P.zz-legal-notice, A.zz-legal-notice-link { font-size : xx-small; /* display : none ; */ /* Uncomment this to hide the legal notice */ } PKs!PKpUIOEBPS/adobj030.gif>>vvv:::rrr***ddd<<<!3,pH,Ȥrl:ШtJZجvzxL.znp%@;q~i5C|3t3suq[11GDMB33Bt}3E1}{DDyBڎz3EĔ114pd ҽ|$yÇc Qaqmdr" \sP@"up CdrHv@.ģHR8C/)Y)0c.c bߌ!APWy"u+"iW fd.^>M Q7ɃP`D2|8xmcȳN 8KVnaĐ .G 6@j/Ȃ)^ DdH먘ɒ$ ‡ឤgF!/i}Pwa ·_qlTD'F eAb\J\6D+r,!!eQA-Iq!0(4h8;:r:{2}gI&JNg5WPw|.OPl K`g>)`T(P +|Y񐶻e X  dІ]ˠ F TLcFt`a`2T l`(q}u^ &P@+N.~S@؀ &m"s" 858du? pYܒ^/$]p𔵛\j(ad(;$ʠ21¥F?0\ X @> lN;@*hC@B8DXFxHJKPF , VxXH+ .p/ C0dXfxhjl؆nprsxxn ~* C0؈8Xxh؉ )X(( p=1R PH#xȋ֑3H !2BhȈ8Xx#؊؍਍ȍXظ(긎|a/=2 #Iя;yxxHиؐ y#Y q( "9Yx*  Y LГ!Z-  3BB7iA.ɐ0 pA 0"@9 `ࠖA2 ҕg :Olz@@]1`3]!`QL1! 9;iZ9!p@Zѓ0ap됍IQ@*aQ Af! ARY$qq 9#M H9i "C@!j -@О0# 2 p'ҡp). A)*Y)"p 3Zz#ZDyU:Y1`G:ـR:TZVzXZ\ڥR@4xh.XF bʣd 55Ҧ6ң0tj+0 ;q |ڧ-@vJNZ+Z#z *ʔʩ⩖ڨ:)J#z ڪ320.*C7E`cmrz9@3 V./3=/cxz"y SVoeC5 |D'='eδW4^3rZgqr lGJګz.HVg>odQj=;..:13S.=D^e}ꬆZӯ^Jd5BӣF[vn[)j$*O1{0t ,+W6>Cpw:>8{=FD<1.AB>sQ+fC* LuQV40u> ;'x=`K`a4P%Q.FU{J ۴W3{^4 C1;T| 562w CGpA`2@H{q{jڠ:{;ś*#:ڼ)+@֋/#۽n:0R({" ˽ =K۾o gRۻ' "<$\&ln!) 0/{, %:<>@BⓂJKRG_PO'9gvmW;; C 'A'CEl31W^M';WW5 0{B6q|Aid@ @ 1P4/k~vMnsCR4(3/id0Є4{0MCc0 DLp)^~xaDyln0l'.0UA۷d:]NafnZ,'4ej&?t/mcOUC)OX'T86i2rt.$?vOcCpe(ǒI+tf OU36'YF0=A>m5Pn9@dRgBsM^cn'uNVKs`JD`^.+h(^KbwMb^q%s태l@غW')4Jw.9~t~`{9&qFO^g|07Z}5>Q82 Bˣku"?Q`;[}4p F[>xONP.؏z}OO+{կ׏VX~/3X4@Lt>QZ^YV(pa18$ivb^c{%')+1 ;=>G"3OQ/SY6IaCcipsuwy{}_kfc/HM 㑦a8`A&T^=3=4@E1fԸcGA9dI'Q!aD/aƔ9fM#.mԹgO8}:hQD@&UiNMF:SWf 1_UjUlYgEmGjƕ;w^Ww%Wo_Y dp:@m.>fbk8oҖ/ca3h/%l!3r0"2~FwkM {.h!b8b <:o  o@@9@.>01"P6":`b@ 8< F8QP@C`  `;"LvDǙ<3B(͛SrN>op3֔IДP7C,u 8@PXBr=:Iyn)l3cCKSB6:!:i7`:?PM^)+ߒCG"tԠFto=P\SBGͶw^ X .NXn!`*eI1X9AYI.QƘ_*ȔV`يUd jm9f}9(!93iT Kg~jAYF:{믦ٶ䋶)9{Y o=֊x[poh< w[1"N?ώ  (iP() .ކ"  xg?)bB tr*ң1&& q,@v'$@}(H&x7\d?@v@?QlYg L @ps:'/p⧿ؙou\`WD|`=HO*ԃd T@y b0pP 0 `&T~ 8@vN".GP@ Wp\ 7F~xE+:T P;.*O1h 5dgD'A/0L)S@Z 1x4aׄɲq_X;M~aW(@wb3 H.^gx P6&1{2]:1rܞJpNH+e5(VV:t,D!tHxry]VuT@`.y/smz`d Dh*wSgPKD=(pG"$&} Uj A~Oh'8?H<@_ެpiюuJ50R/H.w+RMqa(%s+T zlB\/{k$zO }`8rka[Ζ}J't}آ[] *E5b"B oJc)؀2(-G1wt+He*UO`E^1 tՆjRݵxT8"Mn" .p ƒ0ՕoN`;S+Pj1wc7Lq9`@ُ 9Nrؐld39TOfpc!S9NӢ )s0ќfNmvs0Lek`ug=x'{0Ѕ6hE#ЁNERiIOҕ+;PKPKpUIOEBPS/cover.htm Cover

Oracle Corporation

PK;PKpUIOEBPS/adobjadv.htm Advanced Topics for Oracle Objects

7 Advanced Topics for Oracle Objects

The other chapters in this book discuss the topics that you need to get started with Oracle objects. The topics in this chapter are of interest once you start applying object-relational techniques to large-scale applications or complex schemas.

The chapter contains these topics:

Storage of Objects

Oracle automatically maps the complex structure of object types into the simple rectangular structure of tables.

Leaf-Level Attributes

An object type is like a tree structure, where the branches represent the attributes. Attributes that are objects sprout subbranches for their own attributes.

Ultimately, each branch ends at an attribute that is a built-in type; such as NUMBER, VARCHAR2, or REF; or a collection type, such as VARRAY or nested table. Each of these leaf-level attributes of the original object type is stored in a table column.

The leaf-level attributes that are not collection types are called the leaf-level scalar attributes of the object type.

How Row Objects Are Split Across Columns

In an object table, Oracle stores the data for every leaf-level scalar or REF attribute in a separate column. Each VARRAY is also stored in a column, unless it is too large. Oracle stores leaf-level attributes of nested table types in separate tables associated with the object table. You must declare these tables as part of the object table declaration. See "Internal Layout of VARRAYs" and "Internal Layout of Nested Tables".

When you retrieve or change attributes of objects in an object table, Oracle performs the corresponding operations on the columns of the table. Accessing the value of the object itself produces a copy of the object, by invoking the default constructor for the type, using the columns of the object table as arguments.

Oracle stores the system-generated object identifier in a hidden column. Oracle uses the object identifier to construct REFs to the object.

Hidden Columns for Tables with Column Objects

When a table is defined with a column of an object type, Oracle adds hidden columns to the table for the object type's leaf-level attributes. Each object-type column also has a corresponding hidden column to store the NULL information for the column objects (that is, the atomic nulls of the top-level and the nested objects).

Hidden Columns for Substitutable Columns and Tables

A substitutable column or object table has a hidden column not only for each attribute of the column's object type but also for each attribute added in any subtype of the object type. These columns store the values of those attributes for any subtype instances inserted in the substitutable column.

For example, a substitutable column of person_typ will have associated with it a hidden column for each of the attributes of person_typ: idno, name, and phone. It will also have hidden columns for attributes of the subtypes of person_typ. For example, the attributes dept_id and major (for student_typ) and number_hours (for part_time_student_typ).

When a subtype is created, hidden columns for attributes added in the subtype are automatically added to tables containing a substitutable column of any of the new subtype's ancestor types. These retrofit the tables to store data of the new type. If, for some reason, the columns cannot be added, creation of the subtype is rolled back.

When a subtype is dropped with the VALIDATE option to DROP TYPE, all such hidden columns for attributes unique to the subtype are automatically dropped as well if they do not contain data.

A substitutable column also has associated with it a hidden type discriminant column. This column contains an identifier, called a typeid, that identifies the most specific type of each object in the substitutable column. Typically, a typeid (RAW) is one byte, though it can be as big as four bytes for a large hierarchy.

You can find the typeid of a specified object instance using the function SYS_TYPEID. For example, suppose that the substitutable object table person_obj_table contains three rows, as shown in Example 2-17.

The query in Example 7-1 retrieves typeids of object instances stored in the table:

Example 7-1 Retrieving Typeids in a Table

SELECT name, SYS_TYPEID(VALUE(p)) typeid 
  FROM person_obj_table p;


NAME TYPEID
------------------------------ ---------------------------
Bob Jones 01
Joe Lane 02
Kim Patel 03

The catalog views USER_TYPES, DBA_TYPES and ALL_TYPES contain a TYPEID column (not hidden) that gives the typeid value for each type. You can join on this column to get the type names corresponding to the typeids in a type discriminant column. See "SYS_TYPEID" for more information about SYS_TYPEID and typeids.

REFs

When Oracle constructs a REF to a row object, the constructed REF is made up of the object identifier (OID), some metadata of the object table, and, optionally, the ROWID.

The size of a REF in a column of REF type depends on the storage properties associated with the column. For example, if the column is declared as a REF WITH ROWID, Oracle stores the ROWID in the REF column. The ROWID hint is ignored for object references in constrained REF columns.

If column is declared as a REF with a SCOPE clause, the column is made smaller by omitting the object table metadata and the ROWID. A scoped REF is 16 bytes long.

If the object identifier is primary-key based, Oracle may create one or more internal columns to store the values of the primary key depending on how many columns comprise the primary key.


Note:

When a REF column references row objects whose object identifiers are derived from primary keys, we refer to it as a primary-key-based REF or pkREF. Columns containing pkREFs must be scoped or have a referential constraint.

Internal Layout of Nested Tables

The rows of a nested table are stored in a separate storage table. Each nested table column has a single associated storage table, not one for each row. The storage table holds all the elements for all of the nested tables in that column. The storage table has a hidden NESTED_TABLE_ID column with a system-generated value that lets Oracle map the nested table elements back to the appropriate row.

You can speed up queries that retrieve entire collections by making the storage table index-organized. Include the ORGANIZATION INDEX clause inside the STORE AS clause.

A nested table type can contain objects or scalars:

  • If the elements are objects, the storage table is like an object table: the top-level attributes of the object type become the columns of the storage table. But because a nested table row has no object identifier column, you cannot construct REFs to objects in a nested table.

  • If the elements are scalars, the storage table contains a single column called COLUMN_VALUE that contains the scalar values.

See "Nested Table Storage".

Internal Layout of VARRAYs

All the elements of a VARRAY are stored in a single column. Depending upon the size of the array, it may be stored inline or in a BLOB. See Storage Considerations for Varrays for details.

Creating Indexes on Typeids or Attributes

This section discusses the use of indexes on typeids and attributes.

Indexing a Type Discriminant Column

Using the SYS_TYPEID function, you can build an index on the hidden type discriminant column that every substitutable column has. The type discriminant column contains typeids that identify the most specific type of every object instance stored in the substitutable column. This information is used by the system to evaluate queries that use the IS OF predicate to filter by type, but you can access the typeids for your own purposes using the SYS_TYPEID function.


Note:

Generally, a type discriminant column contains only a small number of distinct typeids: at most, there can be only as many as there are types in the related type hierarchy. The low cardinality of this column makes it a good candidate for a bitmap index.

For example, the following statement creates a bitmap index on the type discriminant column underlying the substitutable contact column of table contacts. Function SYS_TYPEID is used to reference the type discriminant column:

CREATE BITMAP INDEX typeid_idx ON contacts (SYS_TYPEID(contact));

Indexing Subtype Attributes of a Substitutable Column

You can build an index on attributes of any of the types that can be stored in a substitutable column. Attributes of subtypes can be referenced in the CREATE INDEX statement by using the TREAT function to filter out types other than the desired subtype (and its subtypes); you then use the dot notation to specify the desired attribute.

For example, the following statement creates an index on the major attribute of all students in the contacts table. The declared type of the contact column is person_typ, of which student_typ is a subtype, so the column may contain instances of person_typ, student_typ, and subtypes of either one:

CREATE INDEX major1_idx ON contacts 
  (TREAT(contact AS student_typ).major);

student_typ is the type that first defined the major attribute: the person_typ supertype does not have it. Consequently, all the values in the hidden column for the major attribute are values for student_typ or parttimestudent_typ authors (a student_typ subtype). This means that the hidden column's values are identical to the values returned by the TREAT expression, which returns major values for all students, including student subtypes: both the hidden column and the TREAT expression list majors for students and nulls for authors of other types. The system exploits this fact and creates index major1_idx as an ordinary B-tree index on the hidden column.

Values in a hidden column are identical to the values returned by a TREAT expression like the preceding one only if the type named as the target of the TREAT function (student_typ) is the type that first defined the attribute. If the target of the TREAT function is a subtype that merely inherited the attribute, as in the following example, the TREAT expression will return non-null major values for the subtype (part-time students) but not for its supertype (other students).

CREATE INDEX major2_idx ON contacts 
  (TREAT(contact AS part_time_student_typ).major);

Here the values stored in the hidden column for major may be different from the results of the TREAT expression. Consequently, an ordinary B-tree index cannot be created on the underlying column. In a case like this, Oracle treats the TREAT expression like any other function-based expression and tries to create the index as a function-based index on the result.

The following example, like the previous one, creates a function-based index on the major attribute of part-time students, but in this case the hidden column for major is associated with a substitutable object table person_obj_table:

CREATE INDEX major3_idx ON person_obj_table p 
  (TREAT(VALUE(p) AS part_time_student_typ).major);

Type Evolution

Changing a object type is called type evolution. You can make the following changes to an object type:

  • Add and drop attributes

  • Add and drop methods

  • Modify a numeric attribute to increase its length, precision, or scale

  • Modify a varying length character attribute to increase its length

  • Change a type's FINAL and INSTANTIABLE properties

  • Modify limit and size of VARRAYs

  • Modify length, precision, and scale of collection elements

Changes to a type affect things that reference the type. For example, if you add a new attribute to a type, data in a column of that type must be presented so as to include the new attribute.

Schema objects that directly or indirectly reference a type and are affected by a change to it are called dependents of the type. A type can have these kinds of dependents:

  • Table

  • Type or subtype

  • Program unit (PL/SQL block): procedure, function, package, trigger

  • Indextype

  • View (including object view)

  • Function-based index

  • Operator

How a dependent schema object is affected by a change to a type depends on the dependent object and on the nature of the change to the type.

All dependent program units, views, operators and indextypes are marked invalid when a type is modified. The next time one of these invalid schema objects is referenced, it is revalidated using the new type definition. If the object recompiles successfully, it becomes valid and can be used again. Depending on the change to the type, function-based indexes may be dropped or disabled and need to be rebuilt.

If a type has dependent tables, then, for each attribute added to a type, one or more internal columns are added to the table depending on the new attribute's type. New attributes are added with NULL values. For each dropped attribute, the columns associated with that attribute are dropped. For each modified attribute, the length, precision, or scale of its associated column is changed accordingly.

These changes mainly involve updating the tables' metadata (information about a table's structure, describing its columns and their types) and can be done quickly. However, the data in those tables must be updated to the format of the new type version as well. Updating this data can be time-consuming if there is a lot of it, so the ALTER TYPE command has options to let you choose whether to convert all dependent table data immediately or to leave it in the old format to be converted piecemeal as it is updated in the course of business.

The CASCADE option for ALTER TYPE propagates a type change to dependent types and tables. See "ALTER TYPE Statement for Type Evolution". CASCADE itself has options that let you choose whether to convert table data to the new type format as part of the propagation: the option INCLUDING TABLE DATA converts the data; the option NOT INCLUDING TABLE DATA does not convert it. By default, the CASCADE option converts the data. In any case, table data is always returned in the format of the latest type version. If the table data is stored in the format of an earlier type version, Oracle converts the data to the format of the latest version before returning it, even though the format in which the data is actually stored is not changed until the data is rewritten.

You can retrieve the definition of the latest type from the system view USER_SOURCE. You can view definitions of all versions of a type in the USER_TYPE_VERSIONS view.

Changes Involved When a Type Is Altered

Only structural changes to a type affect dependent data and require the data to be converted. Changes that are confined to a type's method definitions or behavior (in the type body, where the type's methods are implemented) do not.

These possible changes to a type are structural:

  • Adding an attribute

  • Dropping an attribute

  • Modifying the length, precision, or scale of an attribute

  • Changing the finality of a type (which determines whether subtypes can be derived from it) from FINAL to NOT FINAL or from NOT FINAL to FINAL.

These changes result in new versions of the altered type and all its dependent types and require the system to add, drop, or modify internal columns of dependent tables as part of the process of converting to the new version.

When you make any of these kinds of changes to a type that has dependent types or tables, the effects of propagating the change are not confined only to metadata but affect data storage arrangements and require the data to be converted.

Besides converting data, you may also need to make other changes. For example, if a new attribute is added to a type, and the type body invokes the type's constructor, then each constructor in the type body must be modified to specify a value for the new attribute. Similarly, if a new method is added, then the type body must be replaced to add the implementation of the new method. The type body can be modified by using the CREATE OR REPLACE TYPE BODY statement.

Example 7-2 illustrates how to make a simple change to person_typ by adding one attribute and dropping another. The CASCADE keyword propagates the type change to dependent types and tables, but the phrase NOT INCLUDING TABLE DATA prevents conversion of the related data.

Example 7-2 Altering an Object Type by Adding and Dropping an Attribute

CREATE TABLE person_obj_table OF person_typ;

INSERT INTO person_obj_table 
  VALUES (person_typ(12, 'Bob Jones', '111-555-1212'));

SELECT value(p) FROM person_obj_table p;


VALUE(P)(IDNO, NAME, PHONE)
--------------------------------------------
PERSON_TYP(12, 'Bob Jones', '111-555-1212')
-- add the email attribute and drop the phone attribute
ALTER TYPE person_typ
  ADD ATTRIBUTE (email VARCHAR2(80)), 
  DROP ATTRIBUTE phone CASCADE NOT INCLUDING TABLE DATA;
  
-- Disconnect and reconnect to accommodate the type change
-- The data of table person_obj_table has not been converted yet, but
-- when the data is retrieved, Oracle returns the data based on
-- the latest type version. The new attribute is initialized to NULL.
SELECT value(p) FROM person_obj_table p;


VALUE(P)(IDNO, NAME, EMAIL)
---------------------------------
PERSON_TYP(12, 'Bob Jones', NULL)

During SELECT statements, even though column data may be converted to the latest type version, the converted data is not written back to the column. If a certain user-defined type column in a table is retrieved often, you should consider converting that data to the latest type version to eliminate redundant data conversions. Converting is especially beneficial if the column contains a VARRAY attribute because a VARRAY typically takes more time to convert than an object or nested table column.

You can convert a column of data by issuing an UPDATE statement to set the column to itself. For example:

UPDATE dept_tab SET emp_array_col = emp_array_col;

You can convert all columns in a table by using ALTER TABLE with the UPGRADE INCLUDING DATA. For example:

ALTER TYPE person_typ ADD ATTRIBUTE (photo BLOB)
  CASCADE NOT INCLUDING TABLE DATA;

Altering a Type by Adding a Nested Table Attribute

This section describes the steps required to make a complex change to a type. This change involves the addition of a nested table attribute to an object type that is already included in a nested table. When upgrading the affected nested table, the name of the new storage table is specified.

Assume we have the following schema based on the person_typ object type:

  1. Issue an ALTER TYPE statement to alter the type.

    The default behavior of an ALTER TYPE statement without any option specified is to check if there is any object dependent on the target type. The statement aborts if any dependent object exists. Optional keywords allow cascading the type change to dependent types and tables.

    With the ALTER TYPE statement in Example 7-3, all type and table checks are bypassed to save time and dependent objects are invalidated. Table data cannot be accessed until is validated.

    Example 7-3 Altering an Object Type by Adding a Nested Table Attribute

    -- Create and add a new nested table attribute to person_typ
    CREATE TYPE tasks_typ AS OBJECT (
      priority       VARCHAR2(2),
      description    VARCHAR2(30));
    /
    
    CREATE TYPE tasks_nttab AS TABLE OF tasks_typ;
    /
    
    ALTER TYPE person_typ ADD ATTRIBUTE tasks tasks_nttab
      INVALIDATE;
    
    -- Propagate the change to employee_store_nt
    -- Specify a storage name for the new nested table
    ALTER TABLE employee_store_nt
      UPGRADE NESTED TABLE tasks STORE AS tasks_nt;
    
    
  2. Use CREATE OR REPLACE TYPE BODY to update the corresponding type body to make it current with the new type definition if necessary.

  3. Upgrade the dependent tables to the latest type version and convert the data in the tables.

    Example 7-4 Upgrading Dependent Tables

    ALTER TABLE department UPGRADE INCLUDING DATA;
    
    
  4. Alter dependent PL/SQL program units as needed to take account of changes to the type.

  5. Use OTT or JPUB (or another tool) to generate new header files for applications, depending on whether the application is written in C or Java.

    Adding a new attribute to a supertype also increases the number of attributes in all its subtypes because these inherit the new attribute. Inherited attributes always precede declared (locally defined) attributes, so adding a new attribute to a supertype causes the ordinal position of all declared attributes of any subtype to be incremented by one recursively. The mappings of the altered type must be updated to include the new attributes. OTT and JPUB do this. If you use some other tool, you must be sure that the type headers are properly synchronized with the type definition in the server; otherwise, unpredictable behavior may result.

  6. Modify application code as needed and rebuild the application.

Validating a Type That Has Been Altered

When the system executes an ALTER TYPE statement, it first validates the requested type change syntactically and semantically to make sure it is legal. The system performs the same validations as for a CREATE TYPE statement plus some additional ones. For example, it checks to be sure an attribute being dropped is not used as a partitioning key. If the new spec of the target type or any of its dependent types fails the type validations, the ALTER TYPE statement aborts. No new type version is created, and all dependent objects remain unchanged.

If dependent tables exist, further checking is done to ensure that restrictions relating to the tables and any indexes are observed. Again, if the ALTER TYPE statement fails the check of table-related restrictions, then the type change is aborted, and no new version of the type is created.

When multiple attributes are added in a single ALTER TYPE statement, they are added in the order specified. Multiple type changes can be specified in the same ALTER TYPE statement, but no attribute name or method signature can be specified more than once in the statement. For example, adding and modifying the same attribute in a single statement is not allowed.

For example:

CREATE TYPE mytype AS OBJECT (attr1 NUMBER, attr2 NUMBER);
/
ALTER TYPE mytype ADD ATTRIBUTE (attr3 NUMBER),
  DROP ATTRIBUTE attr2,
  ADD ATTRIBUTE attr4 NUMBER CASCADE;

The resulting definition for mytype becomes:

(attr1 NUMBER, attr3 NUMBER, attr4 NUMBER);

The following ALTER TYPE statement, which attempts to make multiple changes to the same attribute (attr5), is invalid:

-- invalid ALTER TYPE statement
ALTER TYPE mytype ADD ATTRIBUTE (attr5 NUMBER, attr6 CHAR(10)),
  DROP ATTRIBUTE attr5;

The following are other notes on validation constraints, table restrictions, and assorted information about the various kinds of changes that can be made to a type.

Dropping an Attribute

  • Dropping all attributes from a root type is not allowed. You must instead drop the type. Because a subtype inherits all the attributes from its supertype, dropping all the attributes from a subtype does not reduce its attribute count to zero; thus, dropping all attributes declared locally in a subtype is allowed.

  • Only an attribute declared locally in the target type can be dropped. You cannot drop an inherited attribute from a subtype. Instead, drop the attribute from the type where it is locally declared.

  • Dropping an attribute which is part of a table partitioning or sub-partitioning key in a table is not allowed.

  • Dropping an attribute of a primary key OID of an object table or an index-organized table (IOT) is not allowed.

  • When an attribute is dropped, the column corresponding to the dropped attribute is dropped.

  • Indexes, statistics, constraints, and any referential integrity constraints referencing a dropped attribute are removed.

Modifying Attribute Type to Increase the Length, Precision, or Scale

  • Expanding the length of an attribute referenced in a function-based index, clustered key or domain index on a dependent table is not allowed.

Dropping a Method

  • You can drop a method only from the type in which the method is defined (or redefined): You cannot drop an inherited method from a subtype, and you cannot drop an redefined method from a supertype.

  • If a method is not redefined, dropping it using the CASCADE option removes the method from the target type and all subtypes. However, if a method is redefined in a subtype, the CASCADE will fail and roll back. For the CASCADE to succeed, you must first drop each redefined method from the subtype that defines it and only then drop the method from the supertype.

    You can consult the USER_DEPENDENCIES table to find all the schema objects, including types, that depend on a given type. You can also run the DBMS_UTILITY.GET_DEPENDENCY utility to find the dependencies of a type.

  • You can use the INVALIDATE option to drop a method that has been redefined, but the redefined versions in the subtypes must still be dropped manually. The subtypes will remain in an invalid state until they are explicitly altered to drop the redefined versions. Until then, an attempt to recompile the subtypes for revalidation will produce the error Method does not override.

    Unlike CASCADE, INVALIDATE bypasses all the type and table checks and simply invalidates all schema objects dependent on the type. The objects are revalidated the next time they are accessed. This option is faster than using CASCADE, but you must be certain that no problems will be encountered revalidating dependent types and tables. Table data cannot be accessed while a table is invalid; if a table cannot be validated, its data remains inaccessible.

    See "If a Type Change Validation Fails".

Modifying the FINAL or INSTANTIABLE Property

  • Altering an object type from INSTANTIABLE to NOT INSTANTIABLE is allowed only if the type has no table dependents.

  • Altering an object type from NOT INSTANTIABLE to INSTANTIABLE is allowed anytime. This change does not affect tables.

  • Altering an object type from NOT FINAL to FINAL is allowed only if the target type has no subtypes.

  • When you alter an object type from FINAL to NOT FINAL or vice versa, you must use CASCADE to convert data in dependent columns and tables immediately. You may not use the CASCADE option NOT INCLUDING TABLE DATA to defer converting data.

    If you alter a type from NOT FINAL to FINAL, you must use CASCADE INCLUDING TABLE DATA. If you alter a type from FINAL to NOT FINAL, you may use either CASCADE INCLUDING TABLE DATA or CASCADE CONVERT TO SUBSTITUTABLE.

    When you alter a type from FINAL to NOT FINAL. the CASCADE option you should choose depends on whether you want to be able to insert new subtypes of the type you are altering in existing columns and tables.

    By default, altering a type from FINAL to NOT FINAL enables you to create new substitutable tables and columns of that type, but it does not automatically make existing columns (or object tables) of that type substitutable. In fact, just the opposite happens: existing columns and tables of the type are marked NOT SUBSTITUTABLE AT ALL LEVELS. If any embedded attribute of such a column is substitutable, an error is generated. New subtypes of the altered type cannot be inserted in such preexisting columns and tables.

    To alter an object type to NOT FINAL in such a way as to make existing columns and tables of the type substitutable (assuming that they are not marked NOT SUBSTITUTABLE), use the CASCADE option CONVERT TO SUBSTITUTABLE. For example:

    Example 7-5 Converting a Type from FINAL to NOT FINAL

    CREATE TYPE shape AS OBJECT (
        name VARCHAR2(30),
        area NUMBER)
        FINAL;/
    ALTER TYPE shape NOT FINAL CASCADE CONVERT TO SUBSTITUTABLE;
    
    

    This CASCADE option marks each existing column as SUBSTITUTABLE AT ALL LEVELS and causes a new, hidden column to be added for the TypeId of instances stored in the column. The column can then store subtype instances of the altered type.

If a Type Change Validation Fails

The INVALIDATE option of the ALTER TYPE statement lets you alter a type without propagating the type change to dependent objects. In this case, the system does not validate the dependent types and tables to ensure that all the ramifications of the type change are legal. Instead, all dependent schema objects are marked invalid. The objects, including types and tables, are revalidated when next referenced. If a type cannot be revalidated, it remains invalid, and any tables referencing it become inaccessible until the problem is corrected.

A table may fail validation because, for example, adding a new attribute to a type has caused the number of columns in the table to exceed the maximum allowable number of 1000, or because an attribute used as a partitioning or clustering key of a table was dropped from a type.

To force a revalidation of a type, users can issue the ALTER TYPE COMPILE statement. To force a revalidation of an invalid table, users can issue the ALTER TABLE UPGRADE statement and specify whether the data is to be converted to the latest type version. (Note that, in a table validation triggered by the system when a table is referenced, table data is always updated to the latest type version: you do not have the option to postpone conversion of the data.)

If a table is unable to convert to the latest type version, then INSERT, UPDATE and DELETE statements on the table are not allowed and its data becomes inaccessible. The following DDLs can be executed on the table, but all other statements which reference an invalid table are not allowed until the table is successfully validated:

  • DROP TABLE

  • TRUNCATE TABLE

All PL/SQL programs containing variables defined using %ROWTYPE of a table or %TYPE of a column or attribute from a table are compiled based on the latest type version. If the table fails the revalidation, then compiling any program units that reference that table will also fail.

ALTER TYPE Statement for Type Evolution

Table 7-1 lists some of the important options in the ALTER TYPE statement for altering the attribute or method definition of a type.

Table 7-1 ALTER TYPE Options for Type Evolution

Option Description
INVALIDATE Invalidates all dependent objects. Using this option bypasses all the type and table checks, to save time.

Use this option only if you are certain that problems will not be encountered validating dependent types and tables. Table data cannot be accessed again until it is validated; if it cannot be validated, it remains inaccessible.

CASCADE Propagates the type change to dependent types and tables. The statement aborts if an error is found in dependent types or tables unless the FORCE option is specified.

If CASCADE is specified with no other options, then the INCLUDING TABLE DATA option for CASCADE is implied, and Oracle converts all table data to the latest type version.

INCLUDING TABLE DATA Converts data stored in all user-defined columns to the most recent version of the column's type.

For each new attribute added to the column's type, a new attribute is added to the data and is initialized to NULL. For each attribute dropped from the referenced type, the corresponding attribute data is removed from each row in the table. All tablespaces containing the table's data must be in read write mode; otherwise, the statement will not succeed.

NOT INCLUDING TABLE DATA Leaves column data as is, associated with the current type version. If an attribute is dropped from a type referenced by a table, then the corresponding column of the dropped attribute is not removed from the table. Only the metadata of the column is marked unused. If the dropped attribute is stored out-of-line (for example, VARRAY, LOB or nested table attribute) then the out-of-line data is not removed. (Unused columns can be removed afterward by using an ALTER TABLE DROP UNUSED COLUMNS statement.)

This option is useful when you have many large tables and may run out of rollback segments if you convert them all in one transaction. This option enables you to convert the data of each dependent table later in a separate transaction (using an ALTER TABLE UPGRADE INCLUDING DATA statement).

Specifying this option will speed up the table upgrade because the table's data is left in the format of the old type version. However, selecting data from this table will require converting the images stored in the column to the latest type version. This is likely to affect performance during subsequent SELECT statements.

Because this option only requires updating the table's metadata all tablespaces are not required to be on-line in read/write mode for the statement to succeed.

FORCE Forces the system to ignore errors from dependent tables and indexes. Errors are logged in a specified exception table so that they can be queried afterward. This option must be used with caution because dependent tables may become inaccessible if some table errors occur.
CONVERT TO SUBSTITUTABLE For use when altering a type from FINAL to NOT FINAL: Converts data stored in all user-defined columns to the most recent version of the column's type and then marks these existing columns and object tables of the type SUBSTITUTABLE AT ALL LEVELS so that they can store any new subtypes of the type that are created.

If the type is altered to NOT FINAL without specifying this option, existing columns and tables of the type are marked NOT SUBSTITUTABLE AT ALL LEVELS, and new subtypes of the type cannot be stored in them. You will be able to store such subtypes only in columns and tables created after the type was altered.



See Also:

Oracle Database SQL Reference for information about ALTER TYPE options

Figure 7-1 graphically summarizes the options for ALTER TYPE INVALIDATE and their effects. In the figure, T1 is a type and T2 is a dependent type. See the notes following the figure.

Figure 7-1 ALTER TYPE Options

Description of adobj029.gif follows


Notes on the figure:

  1. Invalidate: All objects following line (1) are marked invalid

  2. Cascade Not Including Table Data: All objects following line (2) are marked invalid. Metadata of all dependent tables are upgraded to the latest type version, but the table data are not converted.

  3. Cascade Including Table Data: All objects following line (3) are marked invalid. All dependent tables are upgraded to the latest type version, including the table data.

ALTER TABLE Statement for Type Evolution

You can use ALTER TABLE to convert table data to the latest version of referenced types. For an example of converting table data to latest type version, see "Altering a Type by Adding a Nested Table Attribute". See Table 7-1 for a discussion of the INCLUDING DATA option.


See Also:

Oracle Database SQL Reference for information about ALTER TABLE options

The Attribute-Value Constructor

The system-defined attribute value constructor requires you to pass the constructor a value for each attribute of the type. The constructor then sets the attributes of the new object instance to those values, as shown in Example 7-6.

Example 7-6 Setting the Attribute Value with the Constructor

CREATE TYPE shape AS OBJECT (
    name VARCHAR2(30),
    area NUMBER);
/
CREATE TABLE building_blocks of shape;

-- Attribute value constructor: Sets instance attributes to the specified values
INSERT INTO building_blocks
  VALUES (
    NEW shape('my_shape', 4));

The keyword NEW preceding a call to a constructor is optional but recommended.

Constructors and Type Evolution

The attribute value constructor function saves you the trouble of defining your own constructors for a type. However, with an attribute-value constructor, you must supply a value for every attribute declared in the type. Otherwise the constructor call will fail to compile.

This requirement of an attribute-value constructor can create a problem if you evolve the type later on—by adding an attribute, for example. When you change the attributes of a type, the type's attribute-value constructor changes, too. If you add an attribute, the updated attribute-value constructor expects a value for the new attribute as well as the old ones. As a result, all the attribute-value constructor calls in your existing code, where values for only the old number of attributes are supplied, will fail to compile.

See "Type Evolution".

Advantages of User-Defined Constructors

User-defined constructors avoid the problem with the attribute-value constructor because user-defined constructors do not need to explicitly set a value for every attribute of a type. A user-defined constructor can have any number of arguments, of any type, and these do not need to map directly to type attributes. In your definition of the constructor, you can initialize the attributes to any appropriate values. Any attributes for which you do not supply values are initialized by the system to NULL.

If you evolve a type—for example, by adding an attribute—calls to user-defined constructors for the type do not need to be changed. User-defined constructors, like ordinary methods, are not automatically modified when the type evolves, so the call signature of a user-defined constructor remains the same. You may, however, need to change the definition of the constructor if you do not want the new attribute to be initialized to NULL.

Defining and Implementing User-Defined Constructors

You define user-defined constructors in the type body, like an ordinary method function. You introduce the declaration and the definition with the phrase CONSTRUCTOR FUNCTION; you must also use the clause RETURN SELF AS RESULT.

A constructor for a type must have the same name as the type. Example 7-7 defines two constructor functions for the shape type. As the example shows, you can overload user-defined constructors by defining multiple versions with different signatures.

Example 7-7 Defining and Implementing User-Defined Constructors

CREATE TYPE shape AS OBJECT (
    name VARCHAR2(30),
    area NUMBER,
    CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2)
                               RETURN SELF AS RESULT,
    CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2, 
                               area NUMBER) RETURN SELF AS RESULT
) NOT FINAL;
/

CREATE TYPE BODY shape AS
    CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2) 
                               RETURN SELF AS RESULT IS
    BEGIN
        SELF.name := name;
        SELF.area := 0;
        RETURN;
    END;
    CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2, 
                                area NUMBER) RETURN SELF AS RESULT IS
    BEGIN
        SELF.name := name;
        SELF.area := area;
        RETURN;
    END;
END;
/

A user-defined constructor has an implicit first parameter SELF. Specifying this parameter in the declaration of a user-defined constructor is optional. If you do specify it, its mode must be declared to be IN OUT.

The required clause RETURN SELF AS RESULT ensures that the most specific type of the instance being returned is the same as the most specific type of the SELF argument. In the case of constructors, this is the type for which the constructor is defined.

For example, if the most specific type of the SELF argument on a call to the shape constructor is shape, then this clause ensures that the shape constructor returns an instance of shape (not an instance of a subtype of shape).

When a constructor function is called, the system initializes the attributes of the SELF argument to NULL. Names of attributes subsequently initialized in the function body may be qualified with SELF, as shown in the preceding example, to distinguish them from the names of the arguments of the constructor function, if these are the same. If the argument names are different, no such qualification is necessary. For example:

SELF.name := name;

or:

name := p1;

The function body must include an explicit return; as shown. The return keyword must not be followed by a return expression. The system automatically returns the newly constructed SELF instance.

A user-defined constructor may be implemented in PL/SQL, C, or Java.

Overloading and Hiding Constructors

Like other type methods, user-defined constructors can be overloaded.

User-defined constructors are not inherited, so a user-defined constructor defined in a supertype cannot be hidden in a subtype. However, a user-defined constructor does hide, and thus supersede, the attribute-value constructor for its type if the signature of the user-defined constructor exactly matches the signature of the attribute-value constructor. For the signatures to match, the names and types of the parameters (after the implicit SELF parameter) of the user-defined constructor must be the same as the names and types of the type's attributes. The mode of each of the user-defined constructor's parameters (after the implicit SELF parameter) must be IN.

If an attribute-value constructor is not hidden by a user-defined constructor having the same name and signature, the attribute-value constructor can still be called.

Note that, if you evolve a type—for example, by adding an attribute—the signature of the type's attribute-value constructor changes accordingly. This can cause a formerly hidden attribute-value constructor to become usable again.

Calling User-Defined Constructors

A user-defined constructor is called like any other function. You can use a user-defined constructor anywhere you can use an ordinary function.

The SELF argument is passed in implicitly and may not be passed in explicitly. In other words, usages like the following are not allowed:

NEW constructor(instance, argument_list)

A user-defined constructor cannot occur in the DEFAULT clause of a CREATE or ALTER TABLE statement, but an attribute-value constructor can. The arguments to the attribute-value constructor must not contain references to PL/SQL functions or to other columns, including the pseudocolumns LEVEL, PRIOR, and ROWNUM, or to date constants that are not fully specified. The same is true for check constraint expressions: an attribute-value constructor can be used as part of check constraint expressions while creating or altering a table, but a user-defined constructor cannot.

Parentheses are required in SQL even for constructor calls that have no arguments. In PL/SQL, parentheses are optional when invoking a zero-argument constructor. They do, however, make it more obvious that the constructor call is a function call. The following PL/SQL example omits parentheses in the constructor call to create a new shape:

shape s := NEW my_schema.shape;

The NEW keyword and the schema name are optional.

Example 7-8 creates a subtype under the type created in Example 7-7 and shows examples for calling the user-defined constructors.

Example 7-8 Calling User-Defined Constructors

CREATE TYPE rectangle UNDER shape (
    len NUMBER,
    wth NUMBER,
    CONSTRUCTOR FUNCTION rectangle(SELF IN OUT NOCOPY rectangle,
        name VARCHAR2, len NUMBER, wth NUMBER) RETURN SELF as RESULT,
    CONSTRUCTOR FUNCTION rectangle(SELF IN OUT NOCOPY rectangle,
        name VARCHAR2, side NUMBER) RETURN SELF as RESULT);
/
SHOW ERRORS
CREATE TYPE BODY rectangle IS 
    CONSTRUCTOR FUNCTION rectangle(SELF IN OUT NOCOPY rectangle,
        name VARCHAR2, len NUMBER, wth NUMBER) RETURN  SELF AS RESULT IS
    BEGIN 
        SELF.name := name;
        SELF.area := len*wth;
        SELF.len := len;
        SELF.wth := wth;
        RETURN ;
    END;
    CONSTRUCTOR FUNCTION rectangle(SELF IN OUT NOCOPY rectangle,
        name VARCHAR2, side NUMBER) RETURN  SELF AS RESULT IS
    BEGIN 
        SELF.name := name;
        SELF.area := side * side;
        SELF.len := side;
        SELF.wth := side;
        RETURN ;
    END;
END;
/

CREATE TABLE shape_table OF shape;
INSERT INTO shape_table VALUES(shape('shape1')); 
INSERT INTO shape_table VALUES(shape('shape2', 20)); 
INSERT INTO shape_table VALUES(rectangle('rectangle', 2, 5)); 
INSERT INTO shape_table VALUES(rectangle('quadrangle', 12, 3));
INSERT INTO shape_table VALUES(rectangle('square', 12));

The following query selects the rows in the shape_table:

SELECT VALUE(s) FROM shape_table s;


VALUE(S)(NAME, AREA)
---------------------------------------------
SHAPE('shape1', 0)
SHAPE('shape2', 20)
RECTANGLE('rectangle', 10, 2, 5)
RECTANGLE('quadrangle', 36, 12, 3)
RECTANGLE('square', 144, 12, 12)

The following PL/SQL code calls the constructor:

s shape := NEW shape('void');

Constructors for SQLJ Object Types

A SQLJ object type is a SQL object type mapped to a Java class. A SQLJ object type has an attribute-value constructor. It can also have user-defined constructors that are mapped to constructors in the referenced Java class.

Example 7-9 Creating a SQLJ Object

CREATE TYPE address AS OBJECT 
   EXTERNAL NAME 'university.address' LANGUAGE JAVA
   USING SQLData(
     street   VARCHAR2(100) EXTERNAL NAME 'street',
     city     VARCHAR2(50)  EXTERNAL NAME 'city',
     state    VARCHAR2(50)  EXTERNAL NAME 'state',
     zipcode  NUMBER        EXTERNAL NAME 'zipcode',
    CONSTRUCTOR FUNCTION address (SELF IN OUT NOCOPY address, street VARCHAR2,
                                  city VARCHAR2, state VARCHAR2, zipcode NUMBER)
      RETURN SELF AS RESULT AS LANGUAGE JAVA
      NAME  'university.address (java.lang.String, java.lang.String,
                      java.lang.String, int) return address');
/

A SQLJ type of a serialized representation can have only a user-defined constructor. The internal representation of an object of SQLJ type is opaque to SQL, so an attribute-value constructor is not possible for a DSQLJ type.

Transient and Generic Types

Oracle has three special SQL datatypes that enable you to dynamically encapsulate and access type descriptions, data instances, and sets of data instances of any other SQL type, including object and collection types. You can also use these three special types to create anonymous types, including anonymous collection types.

The three SQL types are implemented as opaque types. In other words, the internal structure of these types is not known to the database; their data can be queried only by implementing functions (typically 3GL routines) for the purpose. Oracle provides both an OCI and a PL/SQL API for implementing such functions.

The three generic SQL types are described in Table 7-2.

Table 7-2 Generic SQL Types

Type Description
SYS.ANYTYPE A type description type. A SYS.ANYTYPE can contain a type description of any SQL type, named or unnamed, including object types and collection types.

An ANYTYPE can contain a type description of a persistent type, but an ANYTYPE itself is transient: in other words, the value in an ANYTYPE itself is not automatically stored in the database. To create a persistent type, use a CREATE TYPE statement from SQL.

SYS.ANYDATA A self-describing data instance type. A SYS.ANYDATA contains an instance of a given type, with data, plus a description of the type. In this sense, a SYS.ANYDATA is self-describing. An ANYDATA can be persistently stored in the database.
SYS.ANYDATASET A self-describing data set type. A SYS.ANYDATASET type contains a description of a given type plus a set of data instances of that type. An ANYDATASET can be persistently stored in the database.

Each of these three types can be used with any built-in type native to the database as well as with object types and collection types, both named and unnamed. The types provide a generic way to work dynamically with type descriptions, lone instances, and sets of instances of other types. Using the APIs, you can create a transient ANYTYPE description of any kind of type. Similarly, you can create or convert (cast) a data value of any SQL type to an ANYDATA and can convert an ANYDATA (back) to a SQL type. And similarly again with sets of values and ANYDATASET.

The generic types simplify working with stored procedures. You can use the generic types to encapsulate descriptions and data of standard types and pass the encapsulated information into parameters of the generic types. In the body of the procedure, you can detail how to handle the encapsulated data and type descriptions of whatever type.

You can also store encapsulated data of a variety of underlying types in one table column of type ANYDATA or ANYDATASET. For example, you can use ANYDATA with Advanced Queuing to model queues of heterogeneous types of data. You can query the data of the underlying datatypes like any other data.

Example 7-10 defines and executes a PL/SQL procedure that uses methods built into SYS.ANYDATA to access information about data stored in a SYS.ANYDATA table column.

Example 7-10 Using SYS.ANYDATA

CREATE OR REPLACE TYPE dogowner AS OBJECT ( 
    ownerno NUMBER, ownername VARCHAR2(10) );
/
CREATE OR REPLACE TYPE dog AS OBJECT ( 
    breed VARCHAR2(10), dogname VARCHAR2(10) );
/
CREATE TABLE mytab ( id NUMBER, data SYS.ANYDATA );
INSERT INTO mytab VALUES ( 1, SYS.ANYDATA.ConvertNumber (5) );
INSERT INTO mytab VALUES ( 2, SYS.ANYDATA.ConvertObject (
    dogowner ( 5555, 'John') ) );
commit;

CREATE OR REPLACE procedure P IS
  CURSOR cur IS SELECT id, data FROM mytab;

  v_id mytab.id%TYPE;
  v_data mytab.data%TYPE;
  v_type SYS.ANYTYPE;
  v_typecode PLS_INTEGER;
  v_typename VARCHAR2(60);
  v_dummy PLS_INTEGER;
  v_n NUMBER;
  v_dogowner dogowner;
  non_null_anytype_for_NUMBER exception;
  unknown_typename exception;

BEGIN
  OPEN cur;
    LOOP
      FETCH cur INTO v_id, v_data;
      EXIT WHEN cur%NOTFOUND;
      v_typecode := v_data.GetType ( v_type /* OUT */ );
      CASE v_typecode
        WHEN Dbms_Types.Typecode_NUMBER THEN
          IF v_type IS NOT NULL
            THEN RAISE non_null_anytype_for_NUMBER; END IF;
          v_dummy := v_data.GetNUMBER ( v_n /* OUT */ );
          Dbms_Output.Put_Line (
            To_Char(v_id) || ': NUMBER = ' || To_Char(v_n) );
        WHEN Dbms_Types.Typecode_Object THEN
          v_typename := v_data.GetTypeName();
          IF v_typename NOT IN ( 'HR.DOGOWNER' )
            THEN RAISE unknown_typename; END IF;
          v_dummy := v_data.GetObject ( v_dogowner /* OUT */ );
          Dbms_Output.Put_Line (
            To_Char(v_id) || ': user-defined type = ' || v_typename ||
            '(' || v_dogowner.ownerno || ', ' || v_dogowner.ownername || ' )' );
      END CASE;
    END LOOP;
    CLOSE cur;

EXCEPTION
  WHEN non_null_anytype_for_NUMBER THEN
      RAISE_Application_Error ( -20000,
        'Paradox: the return AnyType instance FROM GetType ' ||
        'should be NULL for all but user-defined types' );
  WHEN unknown_typename THEN
      RAISE_Application_Error ( -20000,
        'Unknown user-defined type ' || v_typename ||
        ' - program written to handle only HR.DOGOWNER' );
END;
/

SELECT t.data.gettypename() FROM mytab t;
SET SERVEROUTPUT ON;
EXEC P;

The query and the procedure P in the preceding code sample produce output like the following:


T.DATA.GETTYPENAME()
-------------------------------------------------------------
SYS.NUMBER
HR.DOGOWNER

1: NUMBER = 5
2: user-defined type = HR.DOGOWNER(5555, John )

Corresponding to the three generic SQL types are three OCI types that model them. Each has a set of functions for creating and accessing the respective type:

  • OCIType, corresponding to SYS.ANYTYPE

  • OCIAnyData, corresponding to SYS.ANYDATA

  • OCIAnyDataSet, corresponding to SYS.ANYDATASET


    See Also:


User-Defined Aggregate Functions

Oracle provides a number of pre-defined aggregate functions such as MAX, MIN, SUM for performing operations on a set of records. These pre-defined aggregate functions can be used only with scalar data. However, you can create your own custom implementations of these functions, or define entirely new aggregate functions, to use with complex data—for example, with multimedia data stored using object types, opaque types, and LOBs.

User-defined aggregate functions are used in SQL DML statements just like Oracle's own built-in aggregates. Once such functions are registered with the server, Oracle simply invokes the aggregation routines that you supplied instead of the native ones.

User-defined aggregates can be used with scalar data as well. For example, it may be worthwhile to implement special aggregate functions for working with complex statistical data associated with financial or scientific applications.

User-defined aggregates are a feature of the Extensibility Framework. You implement them using ODCIAggregate interface routines.


See Also:

Oracle Database Data Cartridge Developer's Guide for information on using the ODCIAggregate interface routines to implement user-defined aggregate functions

Partitioning Tables That Contain Oracle Objects

Partitioning addresses the key problem of supporting very large tables and indexes by allowing you to decompose them into smaller and more manageable pieces called partitions. Oracle extends partitioning capabilities by letting you partition tables that contain objects, REFs, varrays, and nested tables. Varrays stored in LOBs are equipartitioned in a way similar to LOBs. See also Oracle Database Application Developer's Guide - Large Objects.

Example 7-11 partitions the purchase order table along zip codes (ToZip), which is an attribute of the ShipToAddr embedded column object. For the purposes of this example, the LineItemList nested table was made a varray to illustrate storage for the partitioned varray.


Restriction:

Nested tables are allowed in tables that are partitioned; however, the storage table associated with the nested table is not partitioned.

Example 7-11 Partitioning a Table That Contains Objects

CREATE TYPE LineItemList_vartyp as varray(10000) of LineItem_objtyp;
/
CREATE TYPE PurchaseOrder_typ AS OBJECT ( 
      PONo                NUMBER, 
      Cust_ref            REF Customer_objtyp, 
      OrderDate           DATE, 
      ShipDate            DATE, 
      OrderForm           BLOB, 
      LineItemList        LineItemList_vartyp, 
      ShipToAddr          Address_objtyp, 
 
   MAP MEMBER FUNCTION 
      ret_value RETURN NUMBER, 
   MEMBER FUNCTION 
      total_value RETURN NUMBER);
/
CREATE TABLE PurchaseOrders_tab of PurchaseOrder_typ  
    LOB (OrderForm) store as (nocache logging)  
    PARTITION BY RANGE (ShipToAddr.zip)  
      (PARTITION PurOrderZone1_part  
         VALUES LESS THAN ('59999')  
         LOB (OrderForm) store as (  
               storage (INITIAL 10 MINEXTENTS 10 MAXEXTENTS 100))  
         VARRAY LineItemList store as LOB (  
               storage (INITIAL 10 MINEXTENTS 10 MAXEXTENTS 100)),  
    PARTITION PurOrderZone6_part  
         VALUES LESS THAN ('79999')  
         LOB (OrderForm) store as (  
               storage (INITIAL 10 MINEXTENTS 10 MAXEXTENTS 100))  
         VARRAY LineItemList store as LOB (  
               storage (INITIAL 10 MINEXTENTS 10 MAXEXTENTS 100)),  
    PARTITION PurOrderZoneO_part  
       VALUES LESS THAN ('99999')  
        LOB (OrderForm) store as ( 
               storage (INITIAL 10 MINEXTENTS 10 MAXEXTENTS 100))  
        VARRAY LineItemList store as LOB (  
               storage (INITIAL 10 MINEXTENTS 10 MAXEXTENTS 100)));

How Locators Improve the Performance of Nested Tables

Collection types do not map directly to a native type or structure in languages such as C++ and Java. An application using those languages must access the contents of a collection through Oracle interfaces, such as OCI.

Generally, when the client accesses a nested table explicitly or implicitly (by fetching the containing object), Oracle returns the entire collection value to the client process. For performance reasons, a client may wish to delay or avoid retrieving the entire contents of the collection. Oracle handles this case for you by using a locator instead of the real nested table value. When you really access the contents of the collection, they are automatically transferred to the client.

A nested table locator is like a handle to the collection value. It attempts to preserve the value or copy semantics of the nested table by containing the database snapshot as of its time of retrieval. The snapshot helps the database retrieve the correct instantiation of the nested table value at a later time when the collection elements are fetched using the locator. The locator is scoped to a session and cannot be used across sessions. Because database snapshots are used, it is possible to get a snapshot too old error if there is a high update rate on the nested table. Unlike a LOB locator, the nested table locator is truly a locator and cannot be used to modify the collection instance.

PK*m~#DDPKpUIOEBPS/adobj002.gif!qGIF89an @@@???ϟ///OOO___oooppp 000PPP```! ,n@`H,Ȥrl:D hJZجvzxL\E`n|N|xhVU ʷ  Xư̺}WHP.vjuaH$p0!<(\ T IG,*jÉ&TAyX6d2J SJ22p A.*- p!h `R>6(L #n1 X@8 8@+*U.pJL &`3k2jH,zpͽ=0t{Q;)>XtSzfaڞ?bσ@q]d5 r=*W`9c h3x͔ .祷ކȖ\`~:=Sy#EX}=a]s8!&Xx L6PF)T*12S:mE# yP@c Gn2b!yV18%tp䠄j衈&袇bӖ9`'c#D_Xx U%WVPUZ]RNdto9k`A vfCl aLa"@)q,(4f*t( f0\)l > {ޣjD Ѐ R%;ba8 ?abD`ivɋE8@R%[ JR4S-Hr(@rbQxǠ ;qsX2ʌ5C[UK1$`IhrQ`% ,pie-aB\D'X HH-&b2l$.s憐y14a'Ue"X.C}R21)()yɓS .8|[o#&4:~@EЩ9yH>'xnvr?3ꋍZ M| dwN#b0>!~j7: ?d -- jhMuETgtY{זA|Y͵%2oUV b >d)K ^ {FKҚMjU0&gp@Qͭn$؆C Mr:wamc1:-aѕne!t`r(,w7d @pw=M, Hx%0ɯ~pM" E Y`@MR0ĸ"2]:%ChE` 8q rf-dO|cu4KG"r&GDMr.\()OoU_\nhNqUYd.43Daxγ\ jor' yP2!Q@BEI=TJ@:**b5*+zt##Ji<8yWZZp b2EՀD-bw~v4)0"jw$D 8CDx71J ({hF;`vV|ד+ pol..1b(aeKkj ZZ,e*@G_5,`/ZJ'>fJm<|]/y?]Ӕy]x3NK ӬvtG^)@ۮxϻ0hVFO}GRQ;I8'Oy&~O8c>s~jF0PW)6.#{>d8H @KV{?=hʁԛB9ad }1{շ~[q6kxTH>{?'ȷ*bP'hEng~0 !hwEצ8aԂ q"1E= !mW7Gf=A  y9zQ2FKՒI"֢„MXG&M @ RYdCHzEP$ā"e8 Cc(9Xh#`V.sH;wp@i(}e($;]$Ql@08Q@$ Kxq5UC%|Vr؊0'#z1  mp7dȨQB9!rӘlFmhP"jVshG(XR*gCG{6d!؎+M#B?hяs 0&A80!^VuovPɍ 8QC"N5YC{"iBȒ $kP-L6YA~ؑK eDUWGg9Ss`bNJ>iͰ*1ӱ&!RQ} fGSn&)s|egNDu<}YmEZ \֘P-OT/ iA$Ù+y 8+vw73 Yr>dTxSbg "IZ R&AFЖٙTRya_ Pt,i'bDYy1p H 3ƗYD@ƀ ʠL@n  JaZ% ZY( ڢ]0 c8/-[CPxPZ+9 MZ2QVN$?A^0(VZ14J_p9b;#Tbe8OaFEjidfs:9*"x YVv@|m="Qm頴}y.b.~GiHomVGM]qD"PJ8pDcra+ޱ7]gC$<ٻ.)>+o!%52H2r'Aj%f*!w#8ۻݛEKbQU!V&<*SpjM񔮲x떇[  |L w"<0;aD,,&̭۳Bkq{|uL7t9;lt= ?\CGfA{!>: [G*0V04XŋEfC$a!5̞I _s@lrXm(i%{dzVD d"іS߉ȫ݄\5őd8@WuQɿ4|W^](A^> MH4&6@mRPZs|p6U ?V@D@Sf{NS~љD 4edSkIA`=K`uZ9c/9 #NfkaWJy>"'aц8B١:4E( 3sa7F4ϼ,kPii0p!ETpg⪖ Rw`?up;cLf[|ѬV""V!1=(SP -339m*9hl@ Vh mh%HKmr$mp1kwu]*bS@@@ɗ`srC;%wMYىΐmIG9*]}4fl9.!Ԭ,<3̲X3,?ƅhk` -: uU?0Z≂Fak-^i_Q`EM8 >VKJ@WBޟ\.sLFlMw̰;o (g>\E;%m!wJ4[S@!\*M5 @)C[ 2HdOG,=cF(ZG#%&@ ;M<]z™A'cd8 +T83Ê^Axa*-tAyޚ o~(!D%Ǿe *qFjF F頞cކYFiMߩ?,)Fi irH}s:" ʂR3/hvI{sЅȞ m*d!$Q>MEL GA~?nߥ]\ň7G')ABh@Q BOW0C];:FGJDEHD4{]$@GDsF0o ֭-==a=`y`K43OJA "a)SmA8 (eD|N-1 ߗE&~+flWA={dԁn)FA0nb-&b?t8~{i:: !H~_*p`YR:imHL'b 6TC1~@qJ d.0~ /! Ea.,5&te"InȯE~CT'GkqoP:CRfu.B`x>ga B〨zC @^q@Hd* L^   >"!>.1.B?>>,)" FKI]& >"|<&}#RɟL_AAa3!FaELJԸŋf8$! QYeK BŔ9fM7qԹgZ J@aG&UiSOFP#LպkWG^тgѦUm[6;\ c}7FdA 'FW_ŏ! %|pd˗52>sg&#tm55 ܚv>vr.,loqxs].b*zpø< ŧ|^}^~}o_)4?6(PA}` 0`n iP@` 9>@;,:Ml#@ 0tC6cB>6# 2'o X+#@K-wHΪ@.>,Khs 4P4RN3 Ь : (>*P [E @ P!- @ 6ԴC21E>4U tX|,$]mULj,LQa;\E?e;h 6=4+XӖ; )9R1l QT  vU ʋ<i/҃ ;ajX?e-5c=8=EV;YjM\iqąus 2Ih2vzj駡:"Wj䑫 xQڤN!.Z䤷fƮ[(o9 TxŹP| ܌I @ bR 8q?1WO@>"DXαAa2!\11n}v"F'2!06b}H$.EفQ3_d`@."*qfՁ` Bwd A0  qt -DK9Q@@OS/3@K@&H&uG!! "EP0 H^\lHI04l2Q2tF1m  Jj T< zkY3O\1Lp~79ghx %!S?GW:t%4;\$$[oLBncQ E oq9X\סP"dQ<XPqQ\c3:dG Pb>hD*H. Managing Oracle Objects

6 Managing Oracle Objects

This chapter explains how Oracle objects work in combination with the rest of the database, and how to perform DML and DDL operations on them. It contains the following major sections:

Privileges on Object Types and Their Methods

Privileges for object types exist at the system level and the schema object level.

System Privileges for Object Types

Oracle defines the following system privileges for object types:

  • CREATE TYPE enables you to create object types in your own schema

  • CREATE ANY TYPE enables you to create object types in any schema

  • ALTER ANY TYPE enables you to alter object types in any schema

  • DROP ANY TYPE enables you to drop named types in any schema

  • EXECUTE ANY TYPE enables you to use and reference named types in any schema

  • UNDER ANY TYPE enables you to create subtypes under any non-final object types

  • UNDER ANY VIEW enables you to create subviews under any object view

The RESOURCE role includes the CREATE TYPE system privilege. The DBA role includes all of these privileges.

Schema Object Privileges

Two schema object privileges apply to object types:

  • EXECUTE on an object type enables you to use the type to:

    • Define a table.

    • Define a column in a relational table.

    • Declare a variable or parameter of the named type.

    EXECUTE lets you invoke the type's methods, including the constructor.

    Method execution and the associated permissions are the same as for stored PL/SQL procedures.

  • UNDER enables you to create a subtype or subview under the type or view on which the privilege is granted

    The UNDER privilege on a subtype or subview can be granted only if the grantor has the UNDER privilege on the direct supertype or superview WITH GRANT OPTION.

The phrase WITH HIERARCHY OPTION grants a specified object privilege on all subobjects of the object. This option is meaningful only with the SELECT object privilege granted on an object view in an object view hierarchy. In this case, the privilege applies to all subviews of the view on which the privilege is granted.

Using Types in New Types or Tables

In addition to the permissions detailed in the previous sections, you need specific privileges to:

  • Create types or tables that use types created by other users.

  • Grant use of your new types or tables to other users.

You must have the EXECUTE ANY TYPE system privilege, or you must have the EXECUTE object privilege for any type you use in defining a new type or table. You must have received these privileges explicitly, not through roles.

If you intend to grant access to your new type or table to other users, you must have either the required EXECUTE object privileges with the GRANT option or the EXECUTE ANY TYPE system privilege with the option WITH ADMIN OPTION. You must have received these privileges explicitly, not through roles.

Example: Privileges on Object Types

Assume that three users exist with the CREATE SESSION and RESOURCE roles: USER1, USER2, and USER3.

USER1 performs the following DDL in the USER1 schema:

CONNECT user1/user1
CREATE TYPE type1 AS OBJECT ( attr1 NUMBER );
/
CREATE TYPE type2 AS OBJECT ( attr2 NUMBER );
/
GRANT EXECUTE ON type1 TO user2;
GRANT EXECUTE ON type2 TO user2 WITH GRANT OPTION;

USER2 performs the following DDL in the USER2 schema:

CONNECT user2/user2
CREATE TABLE tab1 OF user1.type1;
CREATE TYPE type3 AS OBJECT ( attr3 user1.type2 );
/
CREATE TABLE tab2 (col1 user1.type2 );

The following statements succeed because USER2 has EXECUTE on USER1's TYPE2 with the GRANT option:

GRANT EXECUTE ON type3 TO user3;
GRANT SELECT ON tab2 TO user3;

However, the following grant fails because USER2 does not have EXECUTE on USER1.TYPE1 with the GRANT option:

GRANT SELECT ON tab1 TO user3 -- incorrect statement;

USER3 can successfully perform the following actions:

CONNECT user3/user3
CREATE TYPE type4 AS OBJECT (attr4 user2.type3);
/
CREATE TABLE tab3 OF type4;

Privileges on Type Access and Object Access

While object types only make use of EXECUTE privilege, object tables use all the same privileges as relational tables:

  • SELECT lets you access an object and its attributes from the table.

  • UPDATE lets you modify attributes of objects in the table.

  • INSERT lets you add new objects to the table.

  • DELETE lets you delete objects from the table.

Similar table and column privileges regulate the use of table columns of object types.

Selecting columns of an object table does not require privileges on the type of the object table. Selecting the entire row object, however, does.

Consider the following schema and queries in Example 6-1:

Example 6-1 SELECT Privileges on Type Access

CREATE TYPE emp_type as object (
  eno     NUMBER,
  ename   VARCHAR2(36));
/
CREATE TABLE emp OF emp_type;
GRANT SELECT on emp TO user1;
SELECT VALUE(e) FROM emp e;
SELECT eno, ename FROM emp;

For either query, Oracle checks the user's SELECT privilege for the emp table. For the first query, the user needs to obtain the emp_type type information to interpret the data. When the query accesses the emp_type type, Oracle checks the user's EXECUTE privilege.

Execution of the second query, however, does not involve named types, so Oracle does not check type privileges.

Additionally, using the schema described in "Example: Privileges on Object Types", USER3 can perform the following queries:

SELECT t.col1.attr2 from user2.tab2 t;

SELECT t.attr4.attr3.attr2 FROM tab3 t;

Note that in both selects by USER3, USER3 does not have explicit privileges on the underlying types, but the statement succeeds because the type and table owners have the necessary privileges with the GRANT option.

Oracle checks privileges on the following requests, and returns an error if the requestor does not have the privilege for the action:

  • Pinning an object in the object cache using its REF value causes Oracle to check SELECT privilege on the object table containing the object and EXECUTE privilege on the object type.


    See Also:

    Oracle Call Interface Programmer's Guide for tips and techniques for using OCI program effectively with objects

  • Modifying an existing object or flushing an object from the object cache, causes Oracle to check UPDATE privilege on the destination object table. Flushing a new object causes Oracle to check INSERT privilege on the destination object table.

  • Deleting an object causes Oracle to check DELETE privilege on the destination table.

  • Invoking a method causes Oracle to check EXECUTE privilege on the corresponding object type.

Oracle does not provide column level privileges for object tables.

Dependencies and Incomplete Types

Types can depend upon each other for their definitions. For example, you might want to define object types employee and department in such a way that one attribute of employee is the department the employee belongs to and one attribute of department is the employee who manages the department.

Types that depend on each other in this way, either directly or through intermediate types, are called mutually dependent. In a diagram that uses arrows to show the dependency relationships among a set of types, connections among mutually dependent types form a loop.

To define such a circular dependency, you must use REFs for at least one segment of the circle.

For example, you can define the types show in Example 6-2.

Example 6-2 Creating Dependent Object Types

CREATE TYPE department;
/

CREATE TYPE employee AS OBJECT (
  name    VARCHAR2(30),
  dept    REF department,
  supv    REF employee );
/

CREATE TYPE emp_list AS TABLE OF employee;
/

CREATE TYPE department AS OBJECT (
  name    VARCHAR2(30),
  mgr     REF employee,
  staff   emp_list );
/

This is a legal set of mutually dependent types and a legal sequence of SQL DDL statements. Oracle compiles it without errors.

Notice that the code in Example 6-2 creates the type department twice. The first statement:

CREATE TYPE department;

is an optional, incomplete declaration of department that serves as a placeholder for the REF attribute of employee to point to. The declaration is incomplete in that it omits the AS OBJECT phrase and lists no attributes or methods. These are specified later in the full declaration that completes the type. In the meantime, department is created as an incomplete object type. This enables the compilation of employee to proceed without errors.

To complete an incomplete type, you execute a CREATE TYPE statement that specifies the attributes and methods of the type, as shown at the end of the example. Complete an incomplete type after all the types that it refers to are created.

If you do not create incomplete types as placeholders, types that refer to the missing types still compile, but the compilation proceeds with errors.

For example, if department did not exist at all, Oracle would create it as an incomplete type and compile employee with errors. Then employee would be recompiled the next time that some operation attempts to access it. This time, if all the types it depends on are created and its dependencies are satisfied, it will compile without errors.

Incomplete types also enable you to create types that contain REF attributes to a subtype that has not yet been created. To create such a supertype, first create an incomplete type of the subtype to be referenced. Create the complete subtype after you create the supertype.

A subtype is just a specialized version of its direct supertype and consequently has an explicit dependency on it. To ensure that subtypes are not left behind after a supertype is dropped, all subtypes must be dropped first: a supertype cannot be dropped until all its subtypes are dropped.

Completing Incomplete Types

When all the types that an incomplete type refers to have been created, there is no longer any need for the incomplete type to remain incomplete, and you should complete the declaration of the type. Completing the type recompiles it and enables the system to release various locks.

You must complete an incomplete object type as an object type: you cannot complete an object type as a collection type (a nested table type or an array type). The only alternative to completing a type declaration is to drop the type.

You must also complete any incomplete types that Oracle creates for you because you did not explicitly create them yourself. The example in the preceding section explicitly creates department as an incomplete type. If department were not explicitly created as an incomplete type, Oracle would create it as one so that the employee type can compile (with errors). You must complete the declaration of department as an object type whether you or Oracle declared it as an incomplete type.

Manually Recompiling a Type

If a type was created with compilation errors, and you attempt an operation on it, such as creating tables or inserting rows, you may receive an error. You need to recompile type typename before attempting the operation. To manually recompile a type, execute an ALTER TYPE typename COMPILE statement. After you have successfully compiled the type, attempt the operation again.

Type Dependencies of Substitutable Tables and Columns

A substitutable table or column of type T is dependent not only on T but on all subtypes of T as well. This is because a hidden column is added to the table for each attribute added in a subtype of T. The hidden columns are added even if the substitutable table or column contains no data of that subtype.

So, for example, a persons table of type person_typ is dependent not only on person_typ but also on the person_typ subtypes student_typ and part_time_student_typ.

If you attempt to drop a subtype that has a dependent type, table, or column, the DROP TYPE statement returns an error and aborts. For example, trying to drop part_time_student_typ will raise an error because of the dependent persons table.

If dependent tables or columns exist but contain no data of the type that you want to drop, you can use the VALIDATE keyword to drop the type. The VALIDATE keyword causes Oracle to check for actual stored instances of the specified type and to drop the type if none are found. Hidden columns associated with attributes unique to the type are removed as well.

For example, the first DROP TYPE statement in the following example fails because part_time_student_typ has a dependent table (persons). But if persons contains no instances of part_time_student_typ (and no other dependent table or column does, either), the VALIDATE keyword causes the second DROP TYPE statement to succeed:

-- Following generates an error due to presence of Persons table 
DROP TYPE part_time_student_typ -- incorrect statement;
-- Following succeeds if there are no stored instances of part_time_student_typ
DROP TYPE part_time_student_typ VALIDATE;


Note:

Oracle recommends that you always use the VALIDATE option while dropping subtypes.

The FORCE Option

The DROP TYPE statement also has a FORCE option that causes the type to be dropped even though it may have dependent types or tables. The FORCE option should be used only with great care, as any dependent types or tables that do exist are marked invalid and become inaccessible when the type is dropped. Data in a table that is marked invalid because a type it depends on has been dropped can never be accessed again. The only action that can be performed on such a table is to drop it.

See "Type Evolution" for information about how to alter a type.

Synonyms for Object Types

Just as you can create synonyms for tables, views, and various other schema objects, you can also define synonyms for object types.

Synonyms for types have the same advantages as synonyms for other kinds of schema objects: they provide a location-independent way to reference the underlying schema object. An application that uses public type synonyms can be deployed without alteration in any schema of a database without having to qualify a type name with the name of the schema in which the type was defined.


See Also:

Oracle Database Administrator's Guide for more information on synonyms in general

Creating a Type Synonym

You create a type synonym with a CREATE SYNONYM statement. For example, these statements create a type typ1 and then create a synonym for it:

-- For the synonym examples, CREATE SYNONYM and CREATE PUBLIC SYNONYM 
-- are granted to USER1
CREATE TYPE typ1 AS OBJECT (x number);
/
CREATE SYNONYM syn1 FOR typ1;

Synonyms can be created for collection types, too. The following example creates a synonym for a nested table type:

CREATE TYPE typ2 AS TABLE OF NUMBER;
/
CREATE SYNONYM syn2 FOR typ2;

You create a public synonym by using the PUBLIC keyword:

CREATE TYPE shape AS OBJECT ( name VARCHAR2(10) );
/
CREATE PUBLIC SYNONYM pub_shape FOR shape;

The REPLACE option enables you to have the synonym point to a different underlying type. For example, the following statement causes syn1 to point to type typ2 instead of the type it formerly pointed to:

CREATE OR REPLACE SYNONYM syn1 FOR typ2;

Using a Type Synonym

You can use a type synonym anywhere that you can refer to a type. For instance, you can use a type synonym in a DDL statement to name the type of a table column or type attribute. In Example 6-3, synonym syn1 is used to specify the type of an attribute in type typ3:

Example 6-3 Using a Type Synonym in a Create Statement

CREATE TYPE typ1 AS OBJECT (x number);
/
CREATE SYNONYM syn1 FOR typ1;

CREATE TYPE typ3 AS OBJECT ( a syn1 );
/

The next example shows a type synonym syn1 used to call the constructor of the object type typ1, for which syn1 is a synonym. The statement returns an object instance of typ1:

SELECT syn1(0) FROM dual;

In the following example, syn2 is a synonym for a nested table type. The example shows the synonym used in place of the actual type name in a CAST expression:

SELECT CAST(MULTISET(SELECT eno FROM USER3.EMP) AS syn2) FROM dual;

Type synonyms can be used in the following kinds of statements:

  • DML statements: SELECT, INSERT, UPDATE, DELETE, FLASHBACK TABLE, EXPLAIN PLAN, and LOCK TABLE

  • DDL statements: AUDIT, NOAUDIT, GRANT, REVOKE, and COMMENT

Describing Schema Objects That Use Synonyms

If a type or table has been created using type synonyms, the DESCRIBE command will show the synonyms in place of the types they represent. Similarly, catalog views, such as USER_TYPE_ATTRS, that show type names will show the associated type synonym names in their place.

You can query the catalog view USER_SYNONYMS to find out the underlying type of a type synonym.

Dependents of Type Synonyms

A type that directly or indirectly references a synonym in its type declaration is a dependent of that synonym. Thus, in the following example, type typ3 is a dependent type of synonym syn1.

CREATE TYPE typ3 AS OBJECT ( a syn1 );
/

Other kinds of schema objects that reference synonyms in their DDL statements also become dependents of those synonyms. An object that depends on a type synonym depends on both the synonym and on the synonym's underlying type.

A synonym's dependency relationships affect your ability to drop or rename the synonym. Dependent schema objects are also affected by some operations on synonyms. The following sections describe these various ramifications.

Restriction on Replacing a Type Synonym

You can replace a synonym only if it has no dependent tables or valid user defined types. Replacing a synonym is equivalent to dropping it and then re-creating a new synonym with the same name.

Dropping Type Synonyms

You drop a synonym with the DROP SYNONYM statement as shown in Example 6-4.

Example 6-4 Dropping Type Synonyms

CREATE SYNONYM syn4 FOR typ1;

DROP SYNONYM syn4;

You cannot drop a type synonym if it has table or valid object types as dependents unless you use the FORCE option. The FORCE option causes any columns that directly or indirectly depend on the synonym to be marked unused, just as if the actual types of the columns were dropped. (A column indirectly depends on a synonym if, for instance, the synonym is used to specify the type of an attribute of the declared type of the column.)

Any dependent schema objects of a dropped synonym are invalidated. They can be revalidated by creating a local object of the same name as the dropped synonym or by creating a new public synonym with same name.

Dropping the underlying base type of a type synonym has the same effect on dependent objects as dropping the synonym.

Renaming Type Synonyms

You can rename a type synonym with the RENAME statement. Renaming a synonym is equivalent to dropping it and then re-creating it with a new name. You cannot rename a type synonym if it has dependent tables or valid object types. The following ex(Vample fails because synonym syn1 has a dependent object type:

RENAME syn1 TO syn3 -- invalid statement;

Public Type Synonyms and Local Schema Objects

You cannot create a local schema object that has the same name as a public synonym if the public synonym has a dependent table or valid object type in the local schema where you want to create the new schema object. Nor can you create a local schema object that has the same name as a private synonym in the same schema.

For instance, in the following example, table shape_tab is a dependent table of public synonym pub_shape because the table has a column that uses the synonym in its type definition. Consequently, the attempt to create a table that has the same name as public synonym pub_shape, in the same schema as the dependent table, fails:

-- Following uses public synonym pub_shape
CREATE TABLE shape_tab ( c1 pub_shape );
-- Following is not allowed
CREATE TABLE pub_shape ( c1 NUMBER ) -- invalid statement;

Performance Tuning

When tuning objects, the following items need to be addressed:

  • How objects and object views consume CPU and memory resources during runtime

  • How to monitor memory and CPU resources during runtime

  • How to manage large numbers of objects

Some of the key performance factors are the following:

  • DBMS_STATS package to collect statistics

  • tkprof to profile execution of SQL commands

  • EXPLAIN PLAN to generate the query plans


    See Also:

    Oracle Database Performance Tuning Guide for details on measuring and tuning the performance of your application

Tools Providing Support for Objects

This section describes several Oracle tools that provide support for Oracle objects.

JDeveloper

JDeveloper is a full-featured, integrated development environment for creating multitier Java applications. It enables you to develop, debug, and deploy Java client applications, dynamic HTML applications, web and application server components and database stored procedures based on industry-standard models.

JDeveloper provides powerful features in the following areas:

  • Oracle Business Components for Java

  • Web Application Development

  • Java Client Application Development

  • Java in the Database

  • Component-Based Development with JavaBeans

  • Simplified Database Access

  • Visual Integrated Development Environment

  • Java Language Support

JDeveloper runs on Windows platforms. It provides a standard GUI based Java development environment that is well integrated with Oracle Application Server and Database.

Business Components for Java (BC4J)

Supporting standard EJB and CORBA deployment architectures, Oracle Business Components for Java simplifies the development, delivery, and customization of Java business applications for the enterprise. Oracle Business Components for Java is an application component framework providing developers a set of reusable software building blocks that manage all the common facilities required to:

  • Author and test business logic in components which integrate with relational databases

  • Reuse business logic through multiple SQL-based views of data

  • Access and update the views from servlets, JavaServer Pages (JSPs), and thin-Java Swing clients

  • Customize application functionality in layers without requiring modification of the delivered application

JPublisher

JPublisher is a utility, written entirely in Java, that generates Java classes to represent the following user-defined database entities in your Java program:

  • Database object types

  • Database reference (REF) types

  • Database collection types (varrays or nested tables)

  • PL/SQL packages

JPublisher enables you to specify and customize the mapping of database object types, reference types, and collection types (varrays or nested tables) to Java classes, in a strongly typed paradigm.

Utilities Providing Support for Objects

This section describes several Oracle utilities that provide support for Oracle objects.

Import/Export of Object Types

The Export and Import utilities move data into and out of Oracle databases. They also back up or archive data and aid migration to different releases of the Oracle RDBMS.

Export and Import support object types. Export writes object type definitions and all of the associated data to the dump file. Import then re-creates these items from the dump file.

Types The definition statements for derived types are exported. On an Import, a subtype may be created before the supertype definition has been imported. In this case, the subtype will be created with compilation errors, which may be ignored. The type will be revalidated after its supertype is created.

Object View Hierarchies View definitions for all views belonging to a view hierarchy are exported

SQL*Loader

The SQL*Loader utility moves data from external files into tables in an Oracle database. The files may contain data consisting of basic scalar datatypes, such as INTEGER, CHAR, or DATE, as well as complex user-defined datatypes such as row and column objects (including objects that have object, collection, or REF attributes), collections, and LOBs. Currently, SQL*Loader supports single-level collections only: you cannot yet use SQL*Loader to load multilevel collections, that is, collections whose elements are, or contain, other collections.

SQL*Loader uses control files, which contain SQL*Loader data definition language (DDL) statements, to describe the format, content, and location of the datafiles.

SQL*Loader provides two approaches to loading data:

  • Conventional path loading, which uses the SQL INSERT statement and a bind array buffer to load data into database tables

  • Direct path loading, which uses the Direct Path Load API to write data blocks directly to the database on behalf of the SQL*Loader client.

    Direct path loading does not use a SQL interface and thus avoids the overhead of processing the associated SQL statements. Consequently, direct path loading tends to provide much better performance than conventional path loading.

Either approach can be used to load data of supported object and collection datatypes.


See Also:

Oracle Database Utilities for instructions on how to use SQL*Loader

PK9PKpUIOEBPS/dcommon/cpyr.htmd Oracle Legal Notices

Oracle Legal Notices

Copyright Notice

Copyright © 1994-2016, Oracle and/or its affiliates. All rights reserved.

License Restrictions Warranty/Consequential Damages Disclaimer

This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.

Warranty Disclaimer

The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.

Restricted Rights Notice

If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, then the following notice is applicable:

U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are "commercial computer software" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs. No other rights are granted to the U.S. Government.

Hazardous Applications Notice

This software or hardware is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications that may create a risk of personal injury. If you use this software or hardware in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software or hardware in dangerous applications.

Trademark Notice

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered trademark of The Open Group.

Third-Party Content, Products, and Services Disclaimer

This software or hardware and documentation may provide access to or information about content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services unless otherwise set forth in an applicable agreement between you and Oracle. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services, except as set forth in an applicable agreement between you and Oracle.

Alpha and Beta Draft Documentation Notice

If this document is in preproduction status:

This documentation is in preproduction status and is intended for demonstration and preliminary use only. It may not be specific to the hardware on which you are using the software. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to this documentation and will not be responsible for any loss, costs, or damages incurred due to the use of this documentation.

Private Alpha and Beta Draft Documentation Notice

If this document is in private preproduction status:

The information contained in this document is for informational sharing purposes only and should be considered in your capacity as a customer advisory board member or pursuant to your beta trial agreement only. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described in this document remains at the sole discretion of Oracle.

This document in any form, software or printed matter, contains proprietary information that is the exclusive property of Oracle. Your access to and use of this confidential material is subject to the terms and conditions of your Oracle Master Agreement, Oracle License and Services Agreement, Oracle PartnerNetwork Agreement, Oracle distribution agreement, or other license agreement which has been executed by you and Oracle and with which you agree to comply. This document and information contained herein may not be disclosed, copied, reproduced, or distributed to anyone outside Oracle without prior written consent of Oracle. This document is not part of your license agreement nor can it be incorporated into any contractual agreement with Oracle or its subsidiaries or affiliates.

Documentation Accessibility

For information about Oracle's commitment to accessibility, visit the Oracle Accessibility Program website at http://www.oracle.com/pls/topic/lookup?ctx=acc&id=docacc.

Access to Oracle Support

Oracle customers that have purchased support have access to electronic support through My Oracle Support. For information, visit http://www.oracle.com/pls/topic/lookup?ctx=acc&id=info or visit http://www.oracle.com/pls/topic/lookup?ctx=acc&id=trs if you are hearing impaired.

Oracle Logo

PKS\UKPKpUIOEBPS/dcommon/oracle.gifJGIF87aiyDT2F'G;Q_oKTC[ 3-Bq{ttsoGc4I)GvmLZ).1)!ꑈ53=Z]'yuLG*)g^!8C?-6(29K"Ĩ0Яl;U+K9^u2,@@ (\Ȱ Ë $P`lj 8x I$4H *(@͉0dа8tA  DсSP v"TUH PhP"Y1bxDǕ̧_=$I /& .)+ 60D)bB~=0#'& *D+l1MG CL1&+D`.1qVG ( "D2QL,p.;u. |r$p+5qBNl<TzB"\9e0u )@D,¹ 2@C~KU 'L6a9 /;<`P!D#Tal6XTYhn[p]݅ 7}B a&AƮe{EɲƮiEp#G}D#xTIzGFǂEc^q}) Y# (tۮNeGL*@/%UB:&k0{ &SdDnBQ^("@q #` @1B4i@ aNȅ@[\B >e007V[N(vpyFe Gb/&|aHZj@""~ӎ)t ? $ EQ.սJ$C,l]A `8A o B C?8cyA @Nz|`:`~7-G|yQ AqA6OzPbZ`>~#8=./edGA2nrBYR@ W h'j4p'!k 00 MT RNF6̙ m` (7%ꑀ;PKl-OJPKpUIOEBPS/dcommon/blafdoc.cssc@charset "utf-8"; /* Copyright 2002, 2011, Oracle and/or its affiliates. All rights reserved. Author: Robert Crews Version: 2011.8.12 */ body { font-family: Tahoma, sans-serif; /* line-height: 125%; */ color: black; background-color: white; font-size: small; } * html body { /* http://www.info.com.ph/~etan/w3pantheon/style/modifiedsbmh.html */ font-size: x-small; /* for IE5.x/win */ f\ont-size: small; /* for other IE versions */ } h1 { font-size: 165%; font-weight: bold; border-bottom: 1px solid #ddd; width: 100%; text-align: left; } h2 { font-size: 152%; font-weight: bold; text-align: left; } h3 { font-size: 139%; font-weight: bold; text-align: left; } h4 { font-size: 126%; font-weight: bold; text-align: left; } h5 { font-size: 113%; font-weight: bold; display: inline; text-align: left; } h6 { font-size: 100%; font-weight: bold; font-style: italic; display: inline; text-align: left; } a:link { color: #039; background: inherit; } a:visited { color: #72007C; background: inherit; } a:hover { text-decoration: underline; } a img, img[usemap] { border-style: none; } code, pre, samp, tt { font-family: monospace; font-size: 110%; } caption { text-align: center; font-weight: bold; width: auto; } dt { font-weight: bold; } table { font-size: small; /* for ICEBrowser */ } td { vertical-align: top; } th { font-weight: bold; text-align: left; vertical-align: bottom; } li { text-align: left; } dd { text-align: left; } ol ol { list-style-type: lower-alpha; } ol ol ol { list-style-type: lower-roman; } td p:first-child, td pre:first-child { margin-top: 0px; margin-bottom: 0px; } table.table-border { border-collapse: collapse; border-top: 1px solid #ccc; border-left: 1px solid #ccc; } table.table-border th { padding: 0.5ex 0.25em; color: black; background-color: #f7f7ea; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; } table.table-border td { padding: 0.5ex 0.25em; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; } span.gui-object, span.gui-object-action { font-weight: bold; } span.gui-object-title { } p.horizontal-rule { width: 100%; border: solid #cc9; border-width: 0px 0px 1px 0px; margin-bottom: 4ex; } div.zz-skip-header { display: none; } td.zz-nav-header-cell { text-align: left; font-size: 95%; width: 99%; color: black; background: inherit; font-weight: normal; vertical-align: top; margin-top: 0ex; padding-top: 0ex; } a.zz-nav-header-link { font-size: 95%; } td.zz-nav-button-cell { white-space: nowrap; text-align: center; width: 1%; vertical-align: top; padding-left: 4px; padding-right: 4px; margin-top: 0ex; padding-top: 0ex; } a.zz-nav-button-link { font-size: 90%; } div.zz-nav-footer-menu { width: 100%; text-align: center; margin-top: 2ex; margin-bottom: 4ex; } p.zz-legal-notice, a.zz-legal-notice-link { font-size: 85%; /* display: none; */ /* Uncomment to hide legal notice */ } /*************************************/ /* Begin DARB Formats */ /*************************************/ .bold, .codeinlinebold, .syntaxinlinebold, .term, .glossterm, .seghead, .glossaryterm, .keyword, .msg, .msgexplankw, .msgactionkw, .notep1, .xreftitlebold { font-weight: bold; } .italic, .codeinlineitalic, .syntaxinlineitalic, .variable, .xreftitleitalic { font-style: italic; } .bolditalic, .codeinlineboldital, .syntaxinlineboldital, .titleinfigure, .titleinexample, .titleintable, .titleinequation, .xreftitleboldital { font-weight: bold; font-style: italic; } .itemizedlisttitle, .orderedlisttitle, .segmentedlisttitle, .variablelisttitle { font-weight: bold; } .bridgehead, .titleinrefsubsect3 { font-weight: bold; } .titleinrefsubsect { font-size: 126%; font-weight: bold; } .titleinrefsubsect2 { font-size: 113%; font-weight: bold; } .subhead1 { display: block; font-size: 139%; font-weight: bold; } .subhead2 { display: block; font-weight: bold; } .subhead3 { font-weight: bold; } .underline { text-decoration: underline; } .superscript { vertical-align: super; } .subscript { vertical-align: sub; } .listofeft { border: none; } .betadraft, .alphabetanotice, .revenuerecognitionnotice { color: #f00; background: inherit; } .betadraftsubtitle { text-align: center; font-weight: bold; color: #f00; background: inherit; } .comment { color: #080; background: inherit; font-weight: bold; } .copyrightlogo { text-align: center; font-size: 85%; } .tocsubheader { list-style-type: none; } table.icons td { padding-left: 6px; padding-right: 6px; } .l1ix dd, dd dl.l2ix, dd dl.l3ix { margin-top: 0ex; margin-bottom: 0ex; } div.infoboxnote, div.infoboxnotewarn, div.infoboxnotealso { margin-top: 4ex; margin-right: 10%; margin-left: 10%; margin-bottom: 4ex; padding: 0.25em; border-top: 1pt solid gray; border-bottom: 1pt solid gray; } p.notep1 { margin-top: 0px; margin-bottom: 0px; } .tahiti-highlight-example { background: #ff9; text-decoration: inherit; } .tahiti-highlight-search { background: #9cf; text-decoration: inherit; } .tahiti-sidebar-heading { font-size: 110%; margin-bottom: 0px; padding-bottom: 0px; } /*************************************/ /* End DARB Formats */ /*************************************/ @media all { /* * * { line-height: 120%; } */ dd { margin-bottom: 2ex; } dl:first-child { margin-top: 2ex; } } @media print { body { font-size: 11pt; padding: 0px !important; } a:link, a:visited { color: black; background: inherit; } code, pre, samp, tt { font-size: 10pt; } #nav, #search_this_book, #comment_form, #comment_announcement, #flipNav, .noprint { display: none !important; } body#left-nav-present { overflow: visible !important; } } PKr.hcPKpUIOEBPS/dcommon/doccd_epub.jsM /* Copyright 2006, 2012, Oracle and/or its affiliates. All rights reserved. Author: Robert Crews Version: 2012.3.17 */ function addLoadEvent(func) { var oldOnload = window.onload; if (typeof(window.onload) != "function") window.onload = func; else window.onload = function() { oldOnload(); func(); } } function compactLists() { var lists = []; var ul = document.getElementsByTagName("ul"); for (var i = 0; i < ul.length; i++) lists.push(ul[i]); var ol = document.getElementsByTagName("ol"); for (var i = 0; i < ol.length; i++) lists.push(ol[i]); for (var i = 0; i < lists.length; i++) { var collapsible = true, c = []; var li = lists[i].getElementsByTagName("li"); for (var j = 0; j < li.length; j++) { var p = li[j].getElementsByTagName("p"); if (p.length > 1) collapsible = false; for (var k = 0; k < p.length; k++) { if ( getTextContent(p[k]).split(" ").length > 12 ) collapsible = false; c.push(p[k]); } } if (collapsible) { for (var j = 0; j < c.length; j++) { c[j].style.margin = "0"; } } } function getTextContent(e) { if (e.textContent) return e.textContent; if (e.innerText) return e.innerText; } } addLoadEvent(compactLists); function processIndex() { try { if (!/\/index.htm(?:|#.*)$/.test(window.location.href)) return false; } catch(e) {} var shortcut = []; lastPrefix = ""; var dd = document.getElementsByTagName("dd"); for (var i = 0; i < dd.length; i++) { if (dd[i].className != 'l1ix') continue; var prefix = getTextContent(dd[i]).substring(0, 2).toUpperCase(); if (!prefix.match(/^([A-Z0-9]{2})/)) continue; if (prefix == lastPrefix) continue; dd[i].id = prefix; var s = document.createElement("a"); s.href = "#" + prefix; s.appendChild(document.createTextNode(prefix)); shortcut.push(s); lastPrefix = prefix; } var h2 = document.getElementsByTagName("h2"); for (var i = 0; i < h2.length; i++) { var nav = document.createElement("div"); nav.style.position = "relative"; nav.style.top = "-1.5ex"; nav.style.left = "1.5em"; nav.style.width = "90%"; while (shortcut[0] && shortcut[0].toString().charAt(shortcut[0].toString().length - 2) == getTextContent(h2[i])) { nav.appendChild(shortcut.shift()); nav.appendChild(document.createTextNode("\u00A0 ")); } h2[i].parentNode.insertBefore(nav, h2[i].nextSibling); } function getTextContent(e) { if (e.textContent) return e.textContent; if (e.innerText) return e.innerText; } } addLoadEvent(processIndex); PKo"nR M PKpUIOEBPS/dcommon/oracle-logo.jpg^`JFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222'7" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE!KEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEzE7V%ȣOΏ9??:a"\fSrğjAsKJ:nOzO=}E1-I)3(QEQEQEQEQEQEQE֝Hza<["2"pO#f8M[RL(,?g93QSZ uy"lx4h`O!LŏʨXZvq& c՚]+: ǵ@+J]tQ]~[[eϸ (]6A&>ܫ~+כzmZ^(<57KsHf妬Ϧmnẁ&F!:-`b\/(tF*Bֳ ~V{WxxfCnMvF=;5_,6%S>}cQQjsOO5=)Ot [W9 /{^tyNg#ЄGsֿ1-4ooTZ?K Gc+oyڙoNuh^iSo5{\ܹ3Yos}$.nQ-~n,-zr~-|K4R"8a{]^;I<ȤL5"EԤP7_j>OoK;*U.at*K[fym3ii^#wcC'IIkIp$󿉵|CtĈpW¹l{9>⪦׺*ͯj.LfGߍԁw] |WW18>w.ӯ! VӃ :#1~ +މ=;5c__b@W@ +^]ևՃ7 n&g2I8Lw7uҭ$"&"b eZ":8)D'%{}5{; w]iu;_dLʳ4R-,2H6>½HLKܹR ~foZKZ࿷1[oZ7׫Z7R¢?«'y?A}C_iG5s_~^ J5?œ tp]X/c'r%eܺA|4ծ-Ե+ْe1M38Ǯ `|Kյ OVڅu;"d56, X5kYR<̭CiطXԮ];Oy)OcWj֩}=܅s۸QZ*<~%뺃ȶp f~Bðzb\ݳzW*y{=[ C/Ak oXCkt_s}{'y?AmCjޓ{ WRV7r. g~Q"7&͹+c<=,dJ1V߁=T)TR՜*N4 ^Bڥ%B+=@fE5ka}ędܤFH^i1k\Sgdk> ֤aOM\_\T)8靠㡮3ģR: jj,pk/K!t,=ϯZ6(((((((49 xn_kLk&f9sK`zx{{y8H 8b4>ÇНE|7v(z/]k7IxM}8!ycZRQ pKVr(RPEr?^}'ðh{x+ՀLW154cK@Ng C)rr9+c:׹b Жf*s^ fKS7^} *{zq_@8# pF~ [VPe(nw0MW=3#kȵz晨cy PpG#W:%drMh]3HH<\]ԁ|_W HHҡb}P>k {ZErxMX@8C&qskLۙOnO^sCk7ql2XCw5VG.S~H8=(s1~cV5z %v|U2QF=NoW]ո?<`~׮}=ӬfԵ,=;"~Iy7K#g{ñJ?5$y` zz@-~m7mG宝Gٱ>G&K#]؃y1$$t>wqjstX.b̐{Wej)Dxfc:8)=$y|L`xV8ߙ~E)HkwW$J0uʟk>6Sgp~;4֌W+חc"=|ř9bc5> *rg {~cj1rnI#G|8v4wĿhFb><^ pJLm[Dl1;Vx5IZ:1*p)إ1ZbAK(1ׅ|S&5{^ KG^5r>;X׻K^? s fk^8O/"J)3K]N)iL?5!ƾq:G_=X- i,vi2N3 |03Qas ! 7}kZU781M,->e;@Qz T(GK(ah(((((((Y[×j2F}o־oYYq $+]%$ v^rϭ`nax,ZEuWSܽ,g%~"MrsrY~Ҿ"Fت;8{ѰxYEfP^;WPwqbB:c?zp<7;SBfZ)dϛ; 7s^>}⍱x?Bix^#hf,*P9S{w[]GF?1Z_nG~]kk)9Sc5Ո<<6J-ϛ}xUi>ux#ţc'{ᛲq?Oo?x&mѱ'#^t)ϲbb0 F«kIVmVsv@}kҡ!ˍUTtxO̧]ORb|2yԵk܊{sPIc_?ħ:Ig)=Z~' "\M2VSSMyLsl⺿U~"C7\hz_ Rs$~? TAi<lO*>U}+'f>7_K N s8g1^CeКÿE ;{+Y\ O5|Y{/o+ LVcO;7Zx-Ek&dpzbӱ+TaB0gNy׭ 3^c T\$⫫?F33?t._Q~Nln:U/Ceb1-im WʸQM+VpafR3d׫é|Aү-q*I P7:y&]hX^Fbtpܩ?|Wu󭏤ʫxJ3ߴm"(uqA}j.+?S wV ~ [B&<^U?rϜ_OH\'.;|.%pw/ZZG'1j(#0UT` Wzw}>_*9m>󑓀F?EL3"zpubzΕ$+0܉&3zڶ+jyr1QE ( ( ( ( ( ( ( (UIdC0EZm+]Y6^![ ԯsmܶ捆?+me+ZE29)B[;я*wGxsK7;5w)}gH~.Ɣx?X\ߚ}A@tQ(:ͧ|Iq(CT?v[sKG+*רqҍck <#Ljα5݈`8cXP6T5i.K!xX*p&ќZǓϘ7 *oƽ:wlຈ:Q5yIEA/2*2jAҐe}k%K$N9R2?7ýKMV!{W9\PA+c4w` Wx=Ze\X{}yXI Ү!aOÎ{]Qx)#D@9E:*NJ}b|Z>_k7:d$z >&Vv󃏽WlR:RqJfGإd9Tm(ҝEtO}1O[xxEYt8,3v bFF )ǙrPNE8=O#V*Cc𹾾&l&cmCh<.P{ʦ&ۣY+Gxs~k5$> ӥPquŽўZt~Tl>Q.g> %k#ú:Kn'&{[yWQGqF}AЅ׮/}<;VYZa$wQg!$;_ $NKS}“_{MY|w7G!"\JtRy+贾d|o/;5jz_6fHwk<ѰJ#]kAȎ J =YNu%dxRwwbEQEQEQEQEQEQEQEQEQE'fLQZ(1F)hQ@X1KEQE-Q@ 1KE3h=iPb(((1GjZ(-ʹRPbR@ 1KE7`bڒyS0(-&)P+ ڎԴP11F)h&:LRmQ@Q@Š(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((_ğ<+F; sU%ԑ >,BH(uSU ^.w$y-9lpoc'sp*Wf>v',ZŠ$1IXO\W3_Bӊ0LoM R<7ca2Ckx->o%u"4MP:A@=BDL#c ȫ ?>M|[_%dG 9x {Um+ŗ6rKFYATҾ,[zChڥY[q"b gQP:5n,F+` 5z/o-a FivVlosQ^Gc-C@ouŶzYKqlF"|-0 5Oӣ/>k$)ːH@OE?lWJx⾣assk0dI[ PNƲlTd X,ZwE@x?pz4M|[yidc! wb ǜg8VP?~j"{oq`j#8>;M;Ėz[#CuAƶ+mݯ!.4iz GnE6$ WYz5K &ӡӢ -#`#EyߏuKBѴC73̇sb׍,W+dd,yk/ᗏ5^vi}Q,ͣhղ w%h&dȿyddEg$Ghp:iGo5 N ~5 ?>M|[_%dG 9x {WYgۻ_|B]Fi&{[ 4܊mI<$ʀ;+⟈43 bn<>ȒAUy3OnMw: cXvDȌ@'fˆǡ8TS|K]j^ ִ_S]9Ŋڛf6}8ʶxYB,\ǡ/"%3C{||:-cB;["]ȁ ,1 ( ( ( ( ( ( ( ( ( ( ( ( (<Ė*>)]?V okC8v׊/6mpit.xU\H%H'1#(;nA|id|2ʰ%K?1SpHq+_/%sAi>m㶙\ZTa 8$q=2?[xž%lz-jQ"b>[ Ĩ2A<^H|K$=^ũrfeD' /b! .vpQr3֬P_^(im/Y9uRH9mK q B_ItOXrM[ @(pdPy]9wXvqX]wk&vMDlppAX'Ծ>/[IJڼ28Is[5qpp,ߠ}J4̿M]#>XiG#Œc3^Eq?5o;> vB7$g j*gvgdH$F Ub>#V|c}˗N}T;O y$rNK ~(L f#o;}W`A(+o5 o/o QbZ6DڒC$ 0}AMX3\OF ndg)+ ԔC]W,伿\}&-2]'THn0T<~ |-7 ;KYpQ$b%1,2Ié Q?(ѷ~ [|/kpN3Š#S8zG |?|7y=O7Z u a_Ƞwd ( ( ( ( ( ( ( ( ( ( ( ( ()xBo@]t]x$zs@|&0wvsj'4?icpwg81\ċ3W󶍦Ku)|k3(nsIL_ſk4MAKY"Ra*U XOp9u="?x gK'$%g_%IVcMcŋ{nڕ߄բ*Kv9N ٵ]56N2} WM°xjGԿ-mh@IpѠJ*7@a|9>N[UsK`A'Ԛ޻I P{\iO4pV-"89@EEqC o_bF۞Pa^Ob Q⋉K]texc8ݐI Fc$O$+??Qo=k+,O4s#(L2` XM(y9vc2}w cl' ٗ.?8Y/)(co2H0'ԓR(g8vt #(l$v#+ߗ<#Z].t31BGh$ ;x\_iw2i ܋2ixtlAv*[ž2ׇXxc#Xpfvb'$Hx]l$iI*׌&dDBϷ}xT?gO IE<nT4-G[|F,t1{41'ѡ.ܫ؄G= & n-h%ME6 H #֦Zkh~UjܺVT17q65Eoo0EexxgEORO G.U֚5JhKy)n! ' n#Zn;[ym^C S* s>VXoxUѴmgǪɩ$vS`Kd1ɮ/ճ|=]1ç|I6Fa2H;{G4Ct~"؈ p 񗆼?rIpgk/6#6 Ǟ9 Am?Q0u/ odIVP3FF=/T "6֊^tyr88:-ΝKÑCO{j[eM>4tviXN㻽+Ʃ{]r&n"|')$TƳ^[ЧhOy.Q&HfXp\TK qXu56I'YHEe#0#8$s\^ROηJfӏ$fD<* Om}^7]3š`񄖉7Wf|ߴ`˓d3Դ7Yi}\:u ʡF@`FpHϹ h杨>,_l`hrON5k3Y&̑ʖo6BJݬυk?D? 1>}yK`~ҷQl@8댮?׬x237åNY˘@7K +SxI>3E]ndj2]!$c#@:;/50ljq%lm?z>r1נOO+K^o5lb5~~6`X=5&Tڧg e]m'D#Ler*8 ."cWڼkُ9rum_QtW>ֳ J7?SеO|x{ŧ"E5Ż'SpJ|Jd`O:}PK-ƃ/;Πv[6p{q0[|IbֱwzeƊa&ו$`vm?2;6'yk~'{6i-nە*@>ރi}LJYwi7)lː%ɉHv#%Wa^F(|QǬHBc>\ #4`FHᶩdA8d2f\!y#>:^<-wi+#3bPH'r9/|k{i$LM9fc6#2P= /<]].0j2v# ! O#@=(((((((((]xS?bڮ/+d߷NjDžo>(5Spf6F߽='8P@]գt/b7H88jK_ᦽxTtM2㸵 K q88#Q\[ tmo[M*kܱ$ƹ$Y>䓎I|#gpOt:B;Oʮl$;:+%?iƵ%IJv s=sKt8[$#0/ ,N690A(B~FfG=!u"u۽@'sO@jlj|}\Ao:1AHE$ qt4QY6NK" V i :`UZktvp6[q;G~RłP(b;xTί O m%i3!RۿI@<a|~ݻgwcY"> 3'%_pF%iw3c#8y_x~Ӯlyi!Gkӷ MHx,t_&30SCt#@-8umZd7mpXj.5Ko hz&+YIyD. {A`~PHTԢԴO, T9Its~Q!rt:Ə<:-mH'X`T 3@Wǟ4IIyOYhֻHa@q p `GtV_|G7Y ynI6#MéVʞ +R ( ( ( ( ( ( ( ( ( ( ( kX__GL>"ԒnQ@Q@Q@c}o iK"oI8 8!'v9 V zŋj=9Zګ.,ss(((((((((('& X]/gvsHع#il9Ǩ'U_[KgPխΛ]i׷gc6rs`UOM;b߽qz5 N/,/.ifGdx،H%H[4W?ЗO˸y~^}!H׮#g7,rgb@vxsH1ˤuKd`a@95_ ]>@v##8@^R'A۝/zo"lC3h*a ⏄,fգ]8o`WoDp30q^|:&h\߮>߻A @1V ?=GDH4FWQWqb8x46;4C02I8>'oikkQ2 ΀9/Cfi},K`&imRx_$w| &_^]լ4/R w4[%n7)?y@zr.ykDE~l&v!%٢$۹qmb13w?e]O羅nn3Ҁ9_Ht/x҉*?ch725ۍCŁco(CF3W#8ȭMo|9Ai:7n*xg HU/]c)G 8h >Ηsqgml $0@; /kM[M5 F.Y . TrA;ѥiV:oiYۦȢN?$y$rMeh.Ukؼ1ebݕ8@Xͼu;MOOQĀžyᵷX$/$0UE$xs\)//ƚNx^Gn`MϕHUvW*+([|$RxJ]J3{ k6fmagkkC n'j(FO'b ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (?PKp7c`^`PKpUIOEBPS/adobjxmp.htm Sample Application Using Object-Relational Features

A Sample Application Using Object-Relational Features

This appendix describes a sample application that provides an overview of how to create and use user-defined datatypes (Oracle Objects). An application is first developed with the relational model and then with the object-relational model.

This appendix contains the following sections:

Introduction to the Sample Application

User-defined types are schema objects in which users formalize the data structures and operations that appear in their applications.

The examples in this appendix illustrate the most important aspects of defining, using, and evolving object types. One important aspect of working with object types is creating methods that perform operations on objects. In the example, definitions of object type methods use the PL/SQL language. Other aspects of using object types, such as defining a type, use SQL.

The examples develop different versions of a database schema for an application that manages customer purchase orders. First a purely relational version is shown, and then an equivalent, object-relational version. Both versions provide for the same basic kinds of entities—customers, purchase orders, line items, and so on. But the object-relational version creates object types for these entities and manages data for particular customers and purchase orders by instantiating instances of the respective object types.

PL/SQL and Java provide additional capabilities beyond those illustrated in this appendix, especially in the area of accessing and manipulating the elements of collections.

Client applications that use the Oracle Call Interface (OCI), Pro*C/C++, or Oracle Objects for OLE (OO4O) can take advantage of its extensive facilities for accessing objects and collections, and manipulating them on clients.


See Also:


Implementing the Schema on the Relational Model

This section implements the relational version of the purchase order schema depicted in Figure A-1.

Entities and Relationships

The basic entities in this example are:

  • Customers

  • The stock of products for sale

  • Purchase orders

As shown in Figure A-1, a customer has contact information, so that the address and set of telephone numbers is exclusive to that customer. The application does not allow different customers to be associated with the same address or telephone numbers. If a customer changes his address, the previous address ceases to exist. If someone ceases to be a customer, the associated address disappears.

A customer has a one-to-many relationship with a purchase order. A customer can place many orders, but a given purchase order is placed by one customer. Because a customer can be defined before he places an order, the relationship is optional rather than mandatory.

Similarly, a purchase order has a many-to-many relationship with a stock item. Because this relationship does not show which stock items appear on which purchase orders, the entity-relationship has the notion of a line item. A purchase order must contain one or more line items. Each line item is associated only with one purchase order. The relationship between line item and stock item is that a stock item can appear on zero, one, or many line items, but each line item refers to exactly one stock item.

Figure A-1 Entity-Relationship Diagram for Purchase Order Application

Description of adobj001.gif follows


Creating Tables Under the Relational Model

The relational approach normalizes everything into tables. The table names are Customer_reltab, PurchaseOrder_reltab, and Stock_reltab.

Each part of an address becomes a column in the Customer_reltab table. Structuring telephone numbers as columns sets an arbitrary limit on the number of telephone numbers a customer can have.

The relational approach separates line items from their purchase orders and puts each into its own table, named PurchaseOrder_reltab and LineItems_reltab.

As depicted in Figure A-1, a line item has a relationship to both a purchase order and a stock item. These are implemented as columns in LineItems_reltab table with foreign keys to PurchaseOrder_reltab and Stock_reltab.


Note:

We have adopted a convention in this section of adding the suffix _reltab to the names of relational tables. Such a self-describing notation can make your code easier to maintain.

You may find it useful to make distinctions between tables (_tab) and types (_typ). But you can choose any names you want; one of the advantages of object-relational constructs is that you can give them names that closely model the corresponding real-world objects.


The relational approach results in the tables describe in the following sections.

Customer_reltab

The Customer_reltab table has the following definition:

Example A-1 Creating the Customer_reltab Table

CREATE TABLE Customer_reltab (
  CustNo                NUMBER NOT NULL,
  CustName              VARCHAR2(200) NOT NULL,
  Street                VARCHAR2(200) NOT NULL,
  City                  VARCHAR2(200) NOT NULL,
  State                 CHAR(2) NOT NULL,
  Zip                   VARCHAR2(20) NOT NULL,
  Phone1                VARCHAR2(20),
  Phone2                VARCHAR2(20),
  Phone3                VARCHAR2(20),
  PRIMARY KEY (CustNo));

This table, Customer_reltab, stores all the information about customers, which means that it fully contains information that is intrinsic to the customer (defined with the NOT NULL constraint) and information that is not as essential. According to this definition of the table, the application requires that every customer have a shipping address.

Our Entity-Relationship (E-R) diagram showed a customer placing an order, but the table does not make allowance for any relationship between the customer and the purchase order. This relationship must be managed by the purchase order.

PurchaseOrder_reltab

The PurchaseOrder_reltab table has the following definition:

Example A-2 Creating the PurchaseOrder_reltab Table

CREATE TABLE PurchaseOrder_reltab (    
   PONo        NUMBER, /* purchase order no */  
   Custno      NUMBER references Customer_reltab, /*  Foreign KEY referencing 
                                                      customer */
   OrderDate   DATE, /*  date of order */  
   ShipDate    DATE, /* date to be shipped */    
   ToStreet    VARCHAR2(200), /* shipto address */    
   ToCity      VARCHAR2(200),    
   ToState     CHAR(2),    
   ToZip       VARCHAR2(20),    
   PRIMARY KEY(PONo));   
  

PurchaseOrder_reltab manages the relationship between the customer and the purchase order by means of the foreign key (FK) column CustNo, which references the CustNo key of the Customer_reltab. The PurchaseOrder_reltab table contains no information about related line items. The line items table (next section) uses the purchase order number to relate a line item to its parent purchase order.

Stock_reltab

The Stock_reltab table has the following definition:

Example A-3 Creating the Stock_reltab Table

CREATE TABLE Stock_reltab (
  StockNo      NUMBER PRIMARY KEY,
  Price        NUMBER,
  TaxRate      NUMBER);

LineItems_reltab

The LineItems_reltab table has the following definition:

Example A-4 Creating the LineItems_reltab Table

CREATE TABLE LineItems_reltab (
  LineItemNo           NUMBER,
  PONo                 NUMBER REFERENCES PurchaseOrder_reltab,
  StockNo              NUMBER REFERENCES Stock_reltab,
  Quantity             NUMBER,
  Discount             NUMBER,
  PRIMARY KEY (PONo, LineItemNo));

Note:

The Stock_reltab and PurchaseOrder_reltab tables must be created before the LineItems_reltab table.

The table name is in the plural form LineItems_reltab to emphasize to someone reading the code that the table holds a collection of line items.

As shown in the E-R diagram, the list of line items has relationships with both the purchase order and the stock item. These relationships are managed by LineItems_reltab by means of two foreign key columns:

  • PONo, which references the PONo column in PurchaseOrder_reltab

  • StockNo, which references the StockNo column in Stock_reltab

Inserting Values Under the Relational Model

In our application, statements like these insert data into the tables:

Example A-5 Establish Inventory

INSERT INTO Stock_reltab VALUES(1004, 6750.00, 2);
INSERT INTO Stock_reltab VALUES(1011, 4500.23, 2);
INSERT INTO Stock_reltab VALUES(1534, 2234.00, 2);
INSERT INTO Stock_reltab VALUES(1535, 3456.23, 2);

Example A-6 Register Customers

INSERT INTO Customer_reltab
  VALUES (1, 'Jean Nance', '2 Avocet Drive',
         'Redwood Shores', 'CA', '95054',
         '415-555-1212', NULL, NULL);

INSERT INTO Customer_reltab
  VALUES (2, 'John Nike', '323 College Drive',
         'Edison', 'NJ', '08820',
         '609-555-1212', '201-555-1212', NULL);

Example A-7 Place Orders

INSERT INTO PurchaseOrder_reltab
  VALUES (1001, 1, SYSDATE, '10-MAY-1997',
          NULL, NULL, NULL, NULL);

INSERT INTO PurchaseOrder_reltab
  VALUES (2001, 2, SYSDATE, '20-MAY-1997',
         '55 Madison Ave', 'Madison', 'WI', '53715');

Example A-8 Detail Line Items

INSERT INTO LineItems_reltab VALUES(01, 1001, 1534, 12,  0);
INSERT INTO LineItems_reltab VALUES(02, 1001, 1535, 10, 10);
INSERT INTO LineItems_reltab VALUES(01, 2001, 1004,  1,  0);
INSERT INTO LineItems_reltab VALUES(02, 2001, 1011,  2,  1);

Querying Data Under the Relational Model

The application can execute queries like these:

Example A-9 Get Customer and Line Item Data for a Specific Purchase Order

SELECT   C.CustNo, C.CustName, C.Street, C.City, C.State,
         C.Zip, C.phone1, C.phone2, C.phone3,
         P.PONo, P.OrderDate,
         L.StockNo, L.LineItemNo, L.Quantity, L.Discount
 FROM    Customer_reltab C,
         PurchaseOrder_reltab P,
         LineItems_reltab L
 WHERE   C.CustNo = P.CustNo
  AND    P.PONo = L.PONo
  AND    P.PONo = 1001;

Example A-10 Get the Total Value of Purchase Orders

SELECT     P.PONo, SUM(S.Price * L.Quantity)
 FROM      PurchaseOrder_reltab P,
           LineItems_reltab L,
           Stock_reltab S
 WHERE     P.PONo = L.PONo
  AND      L.StockNo = S.StockNo
 GROUP BY P.PONo;

Example A-11 Get the Purchase Order and Line Item Data for Stock Item 1004

SELECT    P.PONo, P.CustNo,
          L.StockNo, L.LineItemNo, L.Quantity, L.Discount
 FROM     PurchaseOrder_reltab P,
          LineItems_reltab     L
 WHERE    P.PONo = L.PONo
   AND    L.StockNo = 1004;

Updating Data Under the Relational Model

The application can execute statements like these to update the data:

Example A-12 Update the Quantity for Purchase Order 1001 and Stock Item 1534

UPDATE LineItems_reltab
   SET      Quantity = 20
   WHERE    PONo     = 1001
   AND      StockNo  = 1534;

Deleting Data Under the Relational Model

The application can execute statements similar to Example A-13 to delete data.

Example A-13 Delete Purchase Order 1001 under the Relational Model

DELETE
   FROM   LineItems_reltab
   WHERE  PONo = 1001;

DELETE
   FROM   PurchaseOrder_reltab
   WHERE  PONo = 1001;

Implementing the Schema on the Object-Relational Model

The object-relational approach begins with the same entity relationships as in "Entities and Relationships". Viewing these from the object-oriented perspective, as in the following class diagram, allows us to translate more of the real-world structure into the database schema.

Figure A-2 Class Diagram for Purchase Order Application

Description of adobj002.gif follows


Instead of breaking up addresses or multiple phone numbers into unrelated columns in relational tables, the object-relational approach defines types to represent an entire address and an entire list of phone numbers. Similarly, the object-relational approach uses nested tables to keep line items with their purchase orders instead of storing them separately.

The main entities—customers, stock, and purchase orders—become object types. Object references are used to express some of the relationships among them. Collection types—varrays and nested tables—are used to model multi-valued attributes.


Note:

This appendix implements an object-relational interface by building an object-relational schema from scratch. On this approach, we create object tables for data storage. Alternatively, instead of object tables, you can use object views to implement an object-relational interface to existing data stored in relational tables. Chapter 5 discusses object views.

Defining Types

You create an object type with a CREATE TYPE statement. For example, the following statement creates the type StockItem_objtyp:

Example A-14 Creating the StockItem_objtyp Object

CREATE TYPE StockItem_objtyp AS OBJECT (
  StockNo    NUMBER,
  Price      NUMBER,
  TaxRate    NUMBER
  );
/

Instances of type StockItem_objtyp are objects representing the stock items that customers order. They have three numeric attributes. StockNo is the primary key.

The order in which you define types can make a difference. Ideally, you want to wait to define types that refer to other types until you have defined the other types they refer to.

For example, the type LineItem_objtyp refers to, and thus presupposes, StockItem_objtyp by containing an attribute that is a REF to objects of StockItem_objtyp. You can see this in the statement that creates the type LineItem_objtyp:

Example A-15 Creating the LineItem_objtyp Object

CREATE TYPE LineItem_objtyp AS OBJECT (
  LineItemNo   NUMBER,
  Stock_ref    REF StockItem_objtyp,
  Quantity     NUMBER,
  Discount     NUMBER
  );
/

Instances of type LineItem_objtyp are objects that represent line items. They have three numeric attributes and one REF attribute. The LineItem_objtyp models the line item entity and includes an object reference to the corresponding stock object.

Sometimes the web of references among types makes it difficult or impossible to avoid creating a type before all the types that it presupposes are created. To deal with this sort of situation, you can create what is called an incomplete type to use as a placeholder for other types that you want to create to refer to. Then, when you have created the other types, you can come back and replace the incomplete type with a complete one.

For example, if we had needed to create LineItem_objtyp before we created StockItem_objtyp, we could have used a statement like the following to create LineItem_objtyp as an incomplete type:

CREATE TYPE LineItem_objtyp;

The form of the CREATE TYPE statement used to create an incomplete type lacks that phrase AS OBJECT and also lacks the specification of attributes.

To replace an incomplete type with a complete definition, include the phrase OR REPLACE as shown in the following example:

Example A-16 Replacing the LineItem_objtyp Object

CREATE OR REPLACE TYPE LineItem_objtyp AS OBJECT (
  LineItemNo   NUMBER,
  Stock_ref    REF StockItem_objtyp,
  Quantity     NUMBER,
  Discount     NUMBER
  );
/

It is never wrong to include the words OR REPLACE, even if you have no incomplete type to replace.

Now create the remaining types we need for the schema. The following statement defines an array type for the list of phone numbers:

Example A-17 Creating the PhoneList_vartyp Type

CREATE TYPE PhoneList_vartyp AS VARRAY(10) OF VARCHAR2(20);
/

Any data unit, or instance, of type PhoneList_vartyp is a varray of up to 10 telephone numbers, each represented by a data item of type VARCHAR2.

Either a varray or a nested table could be used to contain a list of phone numbers. In this case, the list is the set of contact phone numbers for a single customer. A varray is a better choice than a nested table for the following reasons:

  • The order of the numbers might be important: varrays are ordered while nested tables are unordered.

  • The number of phone numbers for a specific customer is small. Varrays force you to specify a maximum number of elements (10 in this case) in advance. They use storage more efficiently than nested tables, which have no special size limitations.

  • You can query a nested table but not a varray. But there is no reason to query the phone number list, so using a nested table offers no benefit.

In general, if ordering and bounds are not important design considerations, then designers can use the following rule of thumb for deciding between varrays and nested tables: If you need to query the collection, then use nested tables; if you intend to retrieve the collection as a whole, then use varrays.


See Also:

Chapter 8, "Design Considerations for Oracle Objects" for more information about the design considerations for varrays and nested tables

The following statement defines the object type Address_objtyp to represent addresses:

Example A-18 Creating the Address_objtyp Object

CREATE TYPE Address_objtyp AS OBJECT (
  Street         VARCHAR2(200),
  City           VARCHAR2(200),
  State          CHAR(2),
  Zip            VARCHAR2(20)
  ) 
/

All of the attributes of an address are character strings, representing the usual parts of a simplified mailing address.

The following statement defines the object type Customer_objtyp, which uses other object types as building blocks.

Example A-19 Creating the Customer_objtyp Object

CREATE TYPE Customer_objtyp AS OBJECT (
  CustNo           NUMBER,
  CustName         VARCHAR2(200),
  Address_obj      Address_objtyp,
  PhoneList_var    PhoneList_vartyp,

  ORDER MEMBER FUNCTION
    compareCustOrders(x IN Customer_objtyp) RETURN INTEGER
) NOT FINAL;
/

Instances of the type Customer_objtyp are objects that represent blocks of information about specific customers. The attributes of a Customer_objtyp object are a number, a character string, an Address_objtyp object, and a varray of type PhoneList_vartyp.

The clause NOT FINAL enables us to create subtypes of the customer type later if we wish. By default, types are created as FINAL, which means that the type cannot be further specialized by deriving subtypes from it. We define a subtype of Customer_objtyp for a more specialized kind of customer later in this appendix.

Every Customer_objtyp object also has an associated order method, one of the two types of comparison methods. Whenever Oracle needs to compare two Customer_objtyp objects, it implicitly invokes the compareCustOrders method to do so.


Note:

The PL/SQL to implement the comparison method appears in "The compareCustOrders Method".

The two types of comparison methods are map methods and order methods. This application uses one of each for purposes of illustration.

An ORDER method must be called for every two objects being compared, whereas a map method is called once for each object. In general, when sorting a set of objects, the number of times an ORDER method is called is more than the number of times a map method would be called.


See Also:


The following statement defines a type for a nested table of line items. Each purchase order will use an instance of this nested table type to contain the line items for that purchase order:

Example A-20 Creating the LineItemList_ntabtyp Type

CREATE TYPE LineItemList_ntabtyp AS TABLE OF LineItem_objtyp;
/

An instance of this type is a nested table object (in other words, a nested table), each row of which contains an object of type LineItem_objtyp. A nested table of line items is a better choice to represent the multivalued line item list than a varray of LineItem_objtyp objects, because:

  • Most applications will need to query the contents of line items. This can be done using SQL if the line items are stored in a nested table but not if they are stored in a varray.

  • If an application needs to index on line item data, this can be done with nested tables but not with varrays.

  • The order in which line items are stored is probably not important, and a query can order them by line item number when necessary.

  • There is no practical upper bound on the number of line items on a purchase order. Using a varray requires specifying an arbitrary upper bound on the number of elements.

The following statement defines the object type PurchaseOrder_objtyp:

Example A-21 Creating the PurchaseOrder_objtyp Object

CREATE TYPE PurchaseOrder_objtyp AUTHID CURRENT_USER AS OBJECT (
  PONo                 NUMBER,
  Cust_ref             REF Customer_objtyp,
  OrderDate            DATE,
  ShipDate             DATE,
  LineItemList_ntab    LineItemList_ntabtyp,
  ShipToAddr_obj       Address_objtyp,

  MAP MEMBER FUNCTION
    getPONo RETURN NUMBER,

  MEMBER FUNCTION
    sumLineItems RETURN NUMBER
  );
/

Instances of type PurchaseOrder_objtyp are objects representing purchase orders. They have six attributes, including a REF to Customer_objtyp, an Address_objtyp object, and a nested table of type LineItemList_ntabtyp, which is based on type LineItem_objtyp. PONo is the primary key and Cust_ref is a foreign key.

Objects of type PurchaseOrder_objtyp have two methods: getPONo and sumLineItems. One, getPONo, is a map method, one of the two kinds of comparison methods. A map method returns the relative position of a given record within the order of records within the object. So, whenever Oracle needs to compare two PurchaseOrder_objtyp objects, it implicitly calls the getPONo method to do so.

The two pragma declarations provide information to PL/SQL about what sort of access the two methods need to the database.

The statement does not include the actual PL/SQL programs implementing the methods getPONo and sumLineItems. Those appear in "Method Definitions".

Method Definitions

If a type has no methods, its definition consists just of a CREATE TYPE statement. However, for a type that has methods, you must also define a type body to complete the definition of the type. You do this with a CREATE TYPE BODY statement. As with CREATE TYPE, you can include the words OR REPLACE. You must include this phrase if you are replacing an existing type body with a new one, to change the methods.

The following statement defines the body of the type PurchaseOrder_objtyp. The statement supplies the PL/SQL programs that implement the type's methods:

Example A-22 Creating the PurchaseOrder_objtyp Type Body

CREATE OR REPLACE TYPE BODY PurchaseOrder_objtyp AS 

MAP MEMBER FUNCTION getPONo RETURN NUMBER is   
   BEGIN  
      RETURN PONo;   
   END;    
   
MEMBER FUNCTION sumLineItems RETURN NUMBER is  
      i             INTEGER;  
      StockVal      StockItem_objtyp;  
      Total         NUMBER := 0;  
   
   BEGIN  
      FOR i in 1..SELF.LineItemList_ntab.COUNT LOOP  
         UTL_REF.SELECT_OBJECT(LineItemList_ntab(i).Stock_ref,StockVal);  
         Total := Total + SELF.LineItemList_ntab(i).Quantity * StockVal.Price;  
      END LOOP;  
      RETURN Total;
   END;
END;
/

The getPONo Method

The getPONo method simply returns the value of the PONo attribute—namely, the purchase order number—of whatever instance of the type PurchaseOrder_objtyp that calls the method. Such get methods allow you to avoid reworking code that uses the object if its internal representation changes.

The sumLineItems Method

The sumLineItems method uses a number of object-relational features:

  • As already noted, the basic function of the sumLineItems method is to return the sum of the values of the line items of its associated PurchaseOrder_objtyp object. The keyword SELF, which is implicitly created as a parameter to every function, lets you refer to that object.

  • The keyword COUNT gives the count of the number of elements in a PL/SQL table or array. Here, in combination with LOOP, the application iterates through all the elements in the collection — in this case, the items of the purchase order. In this way SELF.LineItemList_ntab.COUNT counts the number of elements in the nested table that match the LineItemList_ntab attribute of the PurchaseOrder_objtyp object, here represented by SELF.

  • A method from package UTL_REF is used in the implementation. The UTL_REF methods are necessary because Oracle does not support implicit dereferencing of REFs within PL/SQL programs. The UTL_REF package provides methods that operate on object references. Here, the SELECT_OBJECT method is called to obtain the StockItem_objtyp object corresponding to the Stock_ref.

The AUTHID CURRENT_USER syntax specifies that the PurchaseOrder_objtyp is defined using invoker rights: the methods are executed under the rights of the current user, not under the rights of the user who defined the type.

  • The PL/SQL variable StockVal is of type StockItem_objtyp. The UTL_REF.SELECT_OBJECT sets it to the object whose reference is the following:

    (LineItemList_ntab(i).Stock_ref)

    This object is the actual stock item referred to in the currently selected line item.

  • Having retrieved the stock item in question, the next step is to compute its cost. The program refers to the stock item's cost as StockVal.Price, the Price attribute of the StockItem_objtyp object. But to compute the cost of the item, you also need to know the quantity of items ordered. In the application, the term LineItemList_ntab(i).Quantity represents the Quantity attribute of the currently selected LineItem_objtyp object.

The remainder of the method program is a loop that sums the values of the line items. The method returns the total.

The compareCustOrders Method

The following statement defines the compareCustOrders method in the type body of the Customer_objtyp object type:

Example A-23 Creating the Customer_objtyp Type Body

CREATE OR REPLACE TYPE BODY Customer_objtyp AS
  ORDER MEMBER FUNCTION
  compareCustOrders (x IN Customer_objtyp) RETURN INTEGER IS
  BEGIN
    RETURN CustNo - x.CustNo;
  END;
END;
/

As mentioned earlier, the order method compareCustOrders operation compares information about two customer orders. It takes another Customer_objtyp object as an input argument and returns the difference of the two CustNo numbers. The return value is:

  • a negative number if its own object has a smaller value of CustNo

  • a positive number if its own object has a larger value of CustNo

  • zero if the two objects have the same value of CustNo—in which case both orders are associated with the same customer.

Whether the return value is positive, negative, or zero signifies the relative order of the customer numbers. For example, perhaps lower numbers are created earlier in time than higher numbers. If either of the input arguments (SELF and the explicit argument) to an ORDER method is NULL, Oracle does not call the ORDER method and simply treats the result as NULL.

We have now defined all of the object types for the object-relational version of the purchase order schema. We have not yet created any instances of these types to contain actual purchase order data, nor have we created any tables in which to store such data. We show how to do this in the next section.

Creating Object Tables

Creating an object type is not the same as creating a table. Creating a type merely defines a logical structure; it does not create storage. To use an object-relational interface to your data, you must create object types whether you intend to store your data in object tables or leave it in relational tables and access it through object views. Object views and object tables alike presuppose object types: an object table or object view is always a table or view of a certain object type. In this respect it is like a relational column, which always has a specified data type.


See Also:

Chapter 5, "Applying an Object Model to Relational Data" for a discussion of object views

Like a relational column, an object table can contain rows of just one kind of thing, namely, object instances of the same declared type as the table. (And, if the table is substitutable, it can contain instances of subtypes of its declared type as well.)

Each row in an object table is a single object instance. So, in one sense, an object table has, or consists of, only a single column of the declared object type. But this is not as different as it may seem from the case with relational tables. Each row in a relational table theoretically represents a single entity as well—for example, a customer, in a relational Customers table. The columns of a relational table store data for attributes of this entity.

Similarly, in an object table, attributes of the object type map to columns that can be inserted into and selected from. The major difference is that, in an object table, data is stored—and can be retrieved—in the structure defined by the table's type, making it possible for you to retrieve an entire, multilevel structure of data with a very simple query.

The Object Table Customer_objtab

The following statement defines an object table Customer_objtab to hold objects of type Customer_objtyp:

Example A-24 Creating the Customer_objtab Table

CREATE TABLE Customer_objtab OF Customer_objtyp (CustNo PRIMARY KEY) 
   OBJECT IDENTIFIER IS PRIMARY KEY;

Unlike with relational tables, when you create an object table, you specify a data type for it, namely, the type of objects it will contain.

The table has a column for each attribute of Customer_objtyp, namely:


CustNo NUMBER /* Primary key */
CustName VARCHAR2(200)
Address_obj Address_objtyp
PhoneList_var PhoneList_vartyp

See Example A-18, "Creating the Address_objtyp Object" and Example A-17, "Creating the PhoneList_vartyp Type" for the definitions of those types.

Figure A-3 Object Relational Representation of Table Customer_objtab

Description of adobj008.gif follows


Object Datatypes as a Template for Object Tables

Because there is a type Customer_objtyp, you could create numerous object tables of the same type. For example, you could create an object table Customer_objtab2 also of type Customer_objtyp.

You can introduce variations when creating multiple tables. The statement that created Customer_objtab defined a primary key constraint on the CustNo column. This constraint applies only to this object table. Another object table of the same type might not have this constraint.

Object Identifiers and References

Customer_objtab contains customer objects, represented as row objects. Oracle allows row objects to be referenceable, meaning that other row objects or relational rows may reference a row object using its object identifier (OID). For example, a purchase order row object may reference a customer row object using its object reference. The object reference is a system-generated value represented by the type REF and is based on the row object's unique OID.

Oracle requires every row object to have a unique OID. You may specify the unique OID value to be system-generated or specify the row object's primary key to serve as its unique OID. You indicate this when you execute the CREATE TABLE statement by specifying OBJECT IDENTIFIER IS PRIMARY KEY or OBJECT IDENTIFIER IS SYSTEM GENERATED. The latter is the default. Using the primary key as the object identifier can be more efficient in cases where the primary key value is smaller than the default 16 byte system-generated identifier. For our example, the primary key is used as the row object identifier.

Object Tables with Embedded Objects

Note that the Address_obj column of Customer_objtab contains Address_objtyp objects. As this shows, an object type may have attributes that are themselves object types. Object instances of the declared type of an object table are called row objects because one object instance occupies an entire row of the table. But embedded objects such as those in the Address_obj column are referred to as column objects. These differ from row objects in that they do not take up an entire row. Consequently, they are not referenceable—they cannot be the target of a REF. Also, they can be NULL.

The attributes of Address_objtyp objects are of built-in types. They are scalar rather than complex (that is, they are not object types with attributes of their own), and so are called leaf-level attributes to reflect that they represent an end to branching. Columns for Address_objtyp objects and their attributes are created in the object table Customer_objtab. You can refer or navigate to these columns using the dot notation. For example, if you want to build an index on the Zip column, you can refer to it as Address.Zip.

The PhoneList_var column contains varrays of type PhoneList_vartyp. We defined each object of type PhoneList_vartyp as a varray of up to 10 telephone numbers, each represented by a data item of type VARCHAR2. See Example A-17.

Because each varray of type PhoneList_vartyp can contain no more than 200 characters (10 x 20), plus a small amount of overhead, Oracle stores the varray as a single data unit in the PhoneList_var column. Oracle stores varrays that do not exceed 4000 bytes in inline BLOBs, which means that a portion of the varray value could potentially be stored outside the table.

The Object Table Stock_objtab

The next statement creates an object table for StockItem_objtyp objects:

Example A-25 Creating the Stock_objtab Table

CREATE TABLE Stock_objtab OF StockItem_objtyp (StockNo PRIMARY KEY)
   OBJECT IDENTIFIER IS PRIMARY KEY;

Each row of the table is a StockItem_objtyp object having three numeric attributes:


StockNo NUMBER
Price NUMBER
TaxRate NUMBER

Oracle creates a column for each attribute. The CREATE TABLE statement places a primary key constraint on the StockNo column and specifies that the primary key be used as the row object's identifier.

The Object Table PurchaseOrder_objtab

The next statement defines an object table for PurchaseOrder_objtyp objects:

Example A-26 Creating the PurchaseOrder_objtab Table

CREATE TABLE PurchaseOrder_objtab OF PurchaseOrder_objtyp (  /* Line 1 */
   PRIMARY KEY (PONo),                                       /* Line 2 */
   FOREIGN KEY (Cust_ref) REFERENCES Customer_objtab)        /* Line 3 */
   OBJECT IDENTIFIER IS PRIMARY KEY                          /* Line 4 */
   NESTED TABLE LineItemList_ntab STORE AS PoLine_ntab (     /* Line 5 */
     (PRIMARY KEY(NESTED_TABLE_ID, LineItemNo))              /* Line 6 */
     ORGANIZATION INDEX COMPRESS)                            /* Line 7 */
   RETURN AS LOCATOR                                         /* Line 8 */
/   

The preceding CREATE TABLE statement creates the PurchaseOrder_objtab object table. The significance of each line is as follows:

Line 1:


CREATE TABLE PurchaseOrder_objtab OF PurchaseOrder_objtyp (

This line indicates that each row of the table is a PurchaseOrder_objtyp object. Attributes of PurchaseOrder_objtyp objects are:


PONo NUMBER
Cust_ref REF Customer_objtyp
OrderDate DATE
ShipDate DATE
LineItemList_ntab LineItemList_ntabtyp
ShipToAddr_obj Address_objtyp

See Example A-19, "Creating the Customer_objtyp Object" and Example A-20, "Creating the LineItemList_ntabtyp Type" for the definitions of those types.

Figure A-4 Object Relational Representation of Table PurchaseOrder_objtab

Description of adobj009.gif follows


Line 2:

PRIMARY KEY (PONo),

This line specifies that the PONo attribute is the primary key for the table.

Line 3:

FOREIGN KEY (Cust_ref) REFERENCES Customer_objtab)

This line specifies a referential constraint on the Cust_ref column. This referential constraint is similar to those specified for relational tables. When there is no constraint, the REF column permits you to reference any row object. However, in this case, the Cust_ref REFs can refer only to row objects in the Customer_objtab object table.

Line 4:

OBJECT IDENTIFIER IS PRIMARY KEY

This line indicates that the primary key of the PurchaseOrder_objtab object table be used as the row's OID.

Line 5 - 8:


NESTED TABLE LineItemList_ntab STORE AS PoLine_ntab (
(PRIMARY KEY(NESTED_TABLE_ID, LineItemNo))
ORGANIZATION INDEX COMPRESS)
RETURN AS LOCATOR

These lines pertain to the storage specification and properties of the nested table column, LineItemList_ntab. The rows of a nested table are stored in a separate storage table. This storage table cannot be directly queried by the user but can be referenced in DDL statements for maintenance purposes. A hidden column in the storage table, called the NESTED_TABLE_ID, matches the rows with their corresponding parent row. All the elements in the nested table belonging to a particular parent have the same NESTED_TABLE_ID value. For example, all the elements of the nested table of a given row of PurchaseOrder_objtab have the same value of NESTED_TABLE_ID. The nested table elements that belong to a different row of PurchaseOrder_objtab have a different value of NESTED_TABLE_ID.

In the preceding CREATE TABLE example, Line 5 indicates that the rows of LineItemList_ntab nested table are to be stored in a separate table (referred to as the storage table) named PoLine_ntab. The STORE AS clause also permits you to specify the constraint and storage specification for the storage table. In this example, Line 7 indicates that the storage table is an index-organized table (IOT). In general, storing nested table rows in an IOT is beneficial because it provides clustering of rows belonging to the same parent. The specification of COMPRESS on the IOT saves storage space because, if you do not specify COMPRESS, the NESTED_TABLE_ID part of the IOT's key is repeated for every row of a parent row object. If, however, you specify COMPRESS, the NESTED_TABLE_ID is stored only once for each parent row object.


See Also:

"Nested Table Storage" for information about the benefits of organizing a nested table as an IOT, specifying nested table compression, and for more information about nested table storage in general

In Line 6, the specification of NESTED_TABLE_ID and LineItemNo attribute as the primary key for the storage table serves two purposes: first, it specifies the key for the IOT; second, it enforces uniqueness of the column LineItemNo of the nested table within each row of the parent table. By including the LineItemNo column in the key, the statement ensures that the LineItemNo column contains distinct values within each purchase order.

Line 8 indicates that the nested table, LineItemList_ntab, is returned in the locator form when retrieved. If you do not specify LOCATOR, the default is VALUE, which causes the entire nested table to be returned instead of just a locator to it. If a nested table collection contains many elements, it is inefficient to return the entire nested table whenever the containing row object or the column is selected.

Specifying that the nested table's locator is returned enables Oracle to send the client only a locator to the actual collection value. An application can find whether a fetched nested table is in the locator or value form by calling the OCICollIsLocator or UTL_COLL.IS_LOCATOR interfaces. Once you know that the locator has been returned, the application can query using the locator to fetch only the desired subset of row elements in the nested table. This locator-based retrieval of the nested table rows is based on the original statement's snapshot, to preserve the value or copy semantics of the nested table. That is, when the locator is used to fetch a subset of row elements in the nested table, the nested table snapshot reflects the nested table when the locator was first retrieved.

Recall the implementation of the sumLineItems method of PurchaseOrder_objtyp in "Method Definitions". That implementation assumed that the LineItemList_ntab nested table would be returned as a VALUE. In order to handle large nested tables more efficiently, and to take advantage of the fact that the nested table in the PurchaseOrder_objtab is returned as a locator, the sumLineItems method must be rewritten as follows:

Example A-27 Replacing the PurchaseOrder_objtyp Type Body

CREATE OR REPLACE TYPE BODY PurchaseOrder_objtyp AS 

   MAP MEMBER FUNCTION getPONo RETURN NUMBER is   
      BEGIN  
         RETURN PONo;   
      END;   
    
   MEMBER FUNCTION sumLineItems RETURN NUMBER IS  
      i          INTEGER;  
      StockVal   StockItem_objtyp;  
      Total      NUMBER := 0;
  
   BEGIN
      IF (UTL_COLL.IS_LOCATOR(LineItemList_ntab)) -- check for locator
         THEN
            SELECT SUM(L.Quantity * L.Stock_ref.Price) INTO Total
            FROM   TABLE(CAST(LineItemList_ntab AS LineItemList_ntabtyp)) L;
      ELSE
         FOR i in 1..SELF.LineItemList_ntab.COUNT LOOP  
            UTL_REF.SELECT_OBJECT(LineItemList_ntab(i).Stock_ref,StockVal);  
            Total := Total 3; SELF.LineItemList_ntab(i).Quantity * 
                                                            StockVal.Price;  
         END LOOP;  
      END IF;  
   RETURN Total;  
   END;  
END;     
/

The rewritten sumLineItems method checks whether the nested table attribute, LineItemList_ntab, is returned as a locator using the UTL_COLL.IS_LOCATOR function. If the condition evaluates to TRUE, the nested table locator is queried using the TABLE expression.


Note:

The CAST expression is currently required in such TABLE expressions to tell the SQL compilation engine the actual type of the collection attribute (or parameter or variable) so that it can compile the query.

The querying of the nested table locator results in more efficient processing of the large line item list of a purchase order. The previous code that iterates over the LineItemList_ntab is kept to deal with the case where the nested table is returned as a VALUE.

After the table is created, the ALTER TABLE statement is issued to add the SCOPE FOR constraint on a REF. The SCOPE FOR constraint on a REF is not allowed in a CREATE TABLE statement. To specify that Stock_ref can reference only the object table Stock_objtab, issue the following ALTER TABLE statement on the PoLine_ntab storage table:

Example A-28 Adding the SCOPE FOR Constraint

ALTER TABLE PoLine_ntab
   ADD (SCOPE FOR (Stock_ref) IS stock_objtab) ;

This statement specifies that the Stock_ref column of the nested table is scoped to Stock_objtab. This indicates that the values stored in this column must be references to row objects in Stock_objtab. The SCOPE constraint is different from the referential constraint in that the SCOPE constraint has no dependency on the referenced object. For example, any referenced row object in Stock_objtab may be deleted, even if it is referenced in the Stock_ref column of the nested table. Such a deletion renders the corresponding reference in the nested table a DANGLING REF.

Figure A-5 Object Relational Representation of Nested Table LineItemList_ntab

Description of adobj010.gif follows


Oracle does not support a referential constraint specification for storage tables. In this situation, specifying the SCOPE clause for a REF column is useful. In general, specifying scope or referential constraints for REF columns has several benefits:

  • It saves storage space because it allows Oracle to store just the row object's unique identifier as the REF value in the column.

  • It enables an index to be created on the storage table's REF column.

  • It allows Oracle to rewrite queries containing dereferences of these REFs as joins involving the referenced table.

At this point, all of the tables for the purchase order application are in place. The next section shows how to operate on these tables.

Figure A-6 Object Relational Representation of Table PurchaseOrder_objtab

Description of adobj011.gif follows


Inserting Values

Here is how to insert the same data into the object tables that we inserted earlier into relational tables. Notice how some of the values incorporate calls to the constructors for object types, to create instances of the types.

Example A-29 Inserting Values in Stock_objtab

INSERT INTO Stock_objtab VALUES(1004, 6750.00, 2) ;
INSERT INTO Stock_objtab VALUES(1011, 4500.23, 2) ;
INSERT INTO Stock_objtab VALUES(1534, 2234.00, 2) ;
INSERT INTO Stock_objtab VALUES(1535, 3456.23, 2) ;

Example A-30 Inserting Values in Customer_objtab

INSERT INTO Customer_objtab
  VALUES (
    1, 'Jean Nance',
    Address_objtyp('2 Avocet Drive', 'Redwood Shores', 'CA', '95054'),
    PhoneList_vartyp('415-555-1212')
    ) ;

INSERT INTO Customer_objtab
  VALUES (
    2, 'John Nike',
    Address_objtyp('323 College Drive', 'Edison', 'NJ', '08820'),
    PhoneList_vartyp('609-555-1212','201-555-1212')
    ) ;

Example A-31 Inserting Values in PurchaseOrder_objtab

INSERT INTO PurchaseOrder_objtab
  SELECT  1001, REF(C),
          SYSDATE, '10-MAY-1999',
          LineItemList_ntabtyp(),
          NULL
   FROM   Customer_objtab C
   WHERE  C.CustNo = 1 ;

The preceding statement constructs a PurchaseOrder_objtyp object with the following attributes:


PONo 1001
Cust_ref REF to customer number 1
OrderDate SYSDATE
ShipDate 10-MAY-1999
LineItemList_ntab an empty LineItem_ntabtyp
ShipToAddr_obj NULL

The statement uses a query to construct a REF to the row object in the Customer_objtab object table that has a CustNo value of 1.

The following statement uses a TABLE expression to identify the nested table as the target for the insertion, namely the nested table in the LineItemList_ntab column of the row object in the PurchaseOrder_objtab table that has a PONo value of 1001.

Example A-32 Inserting Values in LineItemList_ntab

INSERT INTO TABLE (
  SELECT  P.LineItemList_ntab
   FROM   PurchaseOrder_objtab P
   WHERE  P.PONo = 1001
  )
  SELECT  01, REF(S), 12, 0
   FROM   Stock_objtab S
   WHERE  S.StockNo = 1534 ;

The preceding statement inserts a line item into the nested table identified by the TABLE expression. The inserted line item contains a REF to the row object with a StockNo value of 1534 in the object table Stock_objtab.

The following statements follow the same pattern as the previous ones:

Example A-33 Inserting Values in PurchaseOrder_objtab and LineItemList_ntab

INSERT INTO PurchaseOrder_objtab
  SELECT  2001, REF(C),
          SYSDATE, '20-MAY-1997',
          LineItemList_ntabtyp(),
          Address_objtyp('55 Madison Ave','Madison','WI','53715')
   FROM   Customer_objtab C
   WHERE  C.CustNo = 2 ;

INSERT INTO TABLE (
  SELECT  P.LineItemList_ntab
   FROM   PurchaseOrder_objtab P
   WHERE  P.PONo = 1001
  )
  SELECT  02, REF(S), 10, 10
   FROM   Stock_objtab S
   WHERE  S.StockNo = 1535 ;

INSERT INTO TABLE (
  SELECT  P.LineItemList_ntab
   FROM   PurchaseOrder_objtab P
   WHERE  P.PONo = 2001
  )
  SELECT  10, REF(S), 1, 0
   FROM   Stock_objtab S
   WHERE  S.StockNo = 1004 ;

INSERT INTO TABLE (
  SELECT  P.LineItemList_ntab
   FROM   PurchaseOrder_objtab P
   WHERE  P.PONo = 2001
  )
  VALUES(11, (SELECT REF(S)
    FROM  Stock_objtab S
    WHERE S.StockNo = 1011), 2, 1) ;

Querying

The following query statement implicitly invokes a comparison method. It shows how Oracle orders objects of type PurchaseOrder_objtyp using that type's comparison method:

Example A-34 Query Purchase Orders

SELECT  p.PONo
 FROM   PurchaseOrder_objtab p
 ORDER BY VALUE(p) ;

Oracle invokes the map method getPONo for each PurchaseOrder_objtyp object in the selection. Because that method returns the object's PONo attribute, the selection produces a list of purchase order numbers in ascending numerical order.

The following queries correspond to the queries executed under the relational model.

Example A-35 Query Customer and Line Item Data for Purchase Order 1001

SELECT  DEREF(p.Cust_ref), p.ShipToAddr_obj, p.PONo, 
        p.OrderDate, LineItemList_ntab
 FROM   PurchaseOrder_objtab p
 WHERE  p.PONo = 1001 ;

Example A-36 Query Total Value of Each Purchase Order

SELECT   p.PONo, p.sumLineItems()
 FROM    PurchaseOrder_objtab p ;

Example A-37 Query Purchase Order and Line Item Data for Stock Item 1004

SELECT   po.PONo, po.Cust_ref.CustNo,
         CURSOR (
           SELECT  *
            FROM   TABLE (po.LineItemList_ntab) L
            WHERE  L.Stock_ref.StockNo = 1004
           )
 FROM    PurchaseOrder_objtab po ; 

The preceding query returns a nested cursor for the set of LineItem_obj objects selected from the nested table. The application can fetch from the nested cursor to get the individual LineItem_obj objects. The query can also be expressed by unnesting the nested set with respect to the outer result:

SELECT   po.PONo, po.Cust_ref.CustNo, L.*
 FROM    PurchaseOrder_objtab po, TABLE (po.LineItemList_ntab) L
 WHERE   L.Stock_ref.StockNo = 1004 ;

The preceding query returns the result set as a flattened form (or First Normal Form). This type of query is useful when accessing Oracle collection columns from relational tools and APIs, such as ODBC. In the preceding unnesting example, only the rows of the PurchaseOrder_objtab object table that have any LineItemList_ntab rows are returned. To fetch all rows of the PurchaseOrder_objtab table, regardless of the presence of any rows in their corresponding LineItemList_ntab, then the (+) operator is required:

SELECT   po.PONo, po.Cust_ref.CustNo, L.*
 FROM    PurchaseOrder_objtab po, TABLE (po.LineItemList_ntab) (+) L
 WHERE   L.Stock_ref.StockNo = 1004 ;

In Example A-38, the request requires querying the rows of all LineItemList_ntab nested tables of all PurchaseOrder_objtab rows. Again, unnesting is required:

Example A-38 Query Average Discount across all Line Items of all Purchase Orders

SELECT AVG(L.DISCOUNT)
  FROM PurchaseOrder_objtab po, TABLE (po.LineItemList_ntab) L ;

Deleting

The following example has the same effect as the two deletions needed in the relational case shown in Example A-13. In Example A-39, Oracle deletes the entire purchase order object, including its line items, in a single SQL operation. In the relational case, line items for the purchase order must be deleted from the line items table, and the purchase order must be separately deleted from the purchase orders table.


Note:

I f you are performing the SQL statements in this sample, do not execute the DELETE statement in Example A-39 because the purchase order is needed in the following examples.

Example A-39 Delete Purchase Order 1001 in an Object-Relational Model

DELETE
 FROM   PurchaseOrder_objtab
 WHERE  PONo = 1001 ;

Evolving Object Types

Even a completed, fully built application tends to be a work in progress. Sometimes requirements change, forcing a change an underlying object model or schema to adapt it to new circumstances, and sometimes there are ways to improve an object model so that it does a better job of what it was originally intended to do.

Suppose that, after living with our object-relational application for a while, we discover some ways that we could improve the design. In particular, suppose that we discover that users almost always want to see a history of purchases when they bring up the record for a customer. To do this with the present object model requires a join on the two tables Customer_objtab and PurchaseOrder_objtab that hold information about customers and purchase orders. We decide that a better design would be to provide access to data about related purchase orders directly from the customers table.

One way to do this is to change the Customer_objtyp so that information about a customer's purchase orders is included right in the object instance that represents that customer. In other words, we want to add an attribute for purchase order information to Customer_objtyp. To hold information about multiple purchase orders, the attribute must be a collection type—a nested table.

Adding an attribute is one of several ways that you can alter, or evolve, an object type. When you evolve a type, Oracle applies your changes to the type itself and to all its dependent schema objects, including subtypes of the type, other object types that have the altered type as an attribute, and tables and columns of the altered type.

To change Customer_objtyp to add an attribute for a nested table of purchase orders, several steps are needed:

  1. Create a new type for a nested table of purchase orders

  2. Alter Customer_objtyp to add a new attribute of the new type

  3. In the Customer_objtab object table, name and scope the storage tables for the newly added nested tables

    • Upgrading the Customer_objtab object table for the new attribute actually adds two levels of nested tables, one inside the other, because a purchase order itself contains a nested table of line items.

    • Both the purchase orders nested table and the line items nested table need to be scoped so that they can contain primary key-based REFs. More on this in the next section.

Figure A-7 Nested Tables in the Customer Object Type

Description of adobj034.gif follows


When we are done with the preceding steps, information about customers and purchase orders will be more logically related in our model, and we will be able to query the customers table for all information about customers, purchase orders, and line items. We will also be able to insert a new purchase order for a new customer with a single INSERT statement on the customers table.

Adding an Attribute to the Customer Type

Before we can add a nested table of purchase orders as an attribute of Customer_objtyp, we need to define a type for this sort of nested table. The following statement does this:

Example A-40 Create PurchaseOrderList_ntabtyp

CREATE TYPE PurchaseOrderList_ntabtyp AS TABLE OF PurchaseOrder_objtyp;
/

Now we can use an ALTER TYPE statement to add an attribute of this type to Customer_objtyp:

Example A-41 Alter Customer_objtyp

ALTER TYPE Customer_objtyp
  ADD ATTRIBUTE (PurchaseOrderList_ntab PurchaseOrderList_ntabtyp)
  CASCADE;

If a type being altered has dependent types or tables, an ALTER TYPE statement on the type needs to specify either CASCADE or INVALIDATE to say how to apply the change to the dependents.

  • CASCADE performs validation checks on the dependents before applying a type change. These checks confirm that the change does not entail doing something illegal, such as dropping an attribute that is being used as a partitioning key of a table. If a dependent fails validation, the type change aborts. On the other hand, if all dependents validate successfully, the system goes ahead with whatever changes to metadata and data are required to propagate the change to the type. These can include automatically adding and dropping columns, creating storage tables for nested tables, and so forth.

  • The INVALIDATE option skips the preliminary validation checks and directly applies the type change to dependents. These are then validated the next time that they are accessed. Altering a type this way is saves the time required to do the validations, but if a dependent table cannot be validated later when someone tries to access it, its data cannot be accessed until the table is made to pass the validation.

We need to add scope for a REF column in each of the new nested tables of purchase orders and line items that are added to the Customer_objtab table. For convenience, first we rename the new tables from system-generated names to recognizable names. Then, using the names we have given them, we can alter the storage tables to add scope for their REF columns.

The reason we must do all this is that, in order for a column to store REFs to objects in a table that bases its object identifiers on the primary key, the column must be scoped to that table or have a referential constraint placed on it. Scoping a column to a particular table declares that all REFs in the column are REFs to objects in that table. This declaration is necessary because a primary key-based object identifier is guaranteed unique only in the context of the particular table: it may not be unique across all tables. If you try to insert a primary key-based REF, or user-defined REF, into an unscoped column, you will get an error similar to:

cannot INSERT object view REF or user-defined REF

Line items contain a REF to objects in table Stock_objtab, whose object identifier uses the table's primary key. This is why we had to add scope for the REF column in the storage table for the line items nested table in table PurchaseOrder_objtab after we created that table. Now we have to do it again for the new nested table of line items in table Customer_objtab.

We have to do the same again for the new nested table of purchase orders we are adding in table Customer_objtab: a purchase order references a customer in the table Customer_objtab, and object identifiers in this table are primary-key based as well.

Using the following statement, we determine the names of the system-generated tables so they can be renamed:

SELECT table_name, parent_table_name, parent_table_column FROM user_nested_tables;

The output is similar to the following:

For convenience, rename the system-generated nested tables to appropriate names. For example, using the system-generated names in the previous sample output:

ALTER TABLE "SYSNTQOFArJyBTHu6iOMMKU4wHw==" RENAME TO PO_List_nt;
ALTER TABLE "SYSNTZqu6IQItR++UAtgz1rMB8A==" RENAME TO Items_List_nt;

The process of renaming the system-generated nested tables can also be done automatically with the following PL/SQL procedure:

DECLARE 
  nested_table_1 VARCHAR2(30);
  nested_table_2 VARCHAR2(30);
  cust_obj_table VARCHAR2(30) := 'CUSTOMER_OBJTAB';
BEGIN 
 EXECUTE IMMEDIATE ' SELECT table_name FROM user_nested_tables
    WHERE parent_table_name = :1 ' INTO nested_table_1 USING cust_obj_table;
 EXECUTE IMMEDIATE ' SELECT table_name FROM user_nested_tables
    WHERE parent_table_name = :1 ' INTO nested_table_2 USING nested_table_1;
 EXECUTE IMMEDIATE 'ALTER table "'|| nested_table_1 ||'" RENAME TO PO_List_nt';
 EXECUTE IMMEDIATE 'ALTER table "'|| nested_table_2 ||'" RENAME TO Items_List_nt';
END; 
/

The new storage tables are named PO_List_nt and Items_List_nt. The following statements scope the REF columns in these tables to specific tables:

Example A-42 Add Scope for REF to Nested Tables

ALTER TABLE PO_List_nt ADD (SCOPE FOR (Cust_Ref) IS Customer_objtab);
ALTER TABLE Items_List_nt ADD (SCOPE FOR (Stock_ref) IS Stock_objtab);

There is just one more thing to do before inserting purchase orders for customers in Customer_objtab. An actual nested table of PurchaseOrderList_ntabtyp must be instantiated for each customer in the table.

When a column is added to a table for a new attribute, column values for existing rows are initialized to NULL. This means that each existing customer's nested table of purchase orders is atomically NULL—there is no actual nested table there, not even an empty one. Until we instantiate a nested table for each customer, attempts to insert purchase orders will get an error similar to:

reference to NULL table value

The following statement prepares the column to hold purchase orders by updating each row to contain an actual nested table instance:

Example A-43 Update Customer_objtab

UPDATE Customer_objtab c
  SET c.PurchaseOrderList_ntab = PurchaseOrderList_ntabtyp();

In the preceding statement, PurchaseOrderList_ntabtyp() is a call to the nested table type's constructor method. This call, with no purchase orders specified, creates an empty nested table.

Working with Multilevel Collections

At this point, we have evolved the type Customer_objtyp to add a nested table of purchase orders, and we have set up the table Customer_objtab so that it is ready to store purchase orders in the nested table. Now we are ready to insert purchase orders into Customer_objtab.

There are two purchase orders already in table PurchaseOrder_objtab. The following two statements copy these into Customer_objtab:

Example A-44 Insert Purchase Orders into Customer_objtab

INSERT INTO TABLE (
  SELECT   c.PurchaseOrderList_ntab
    FROM   Customer_objtab c
    WHERE  c.CustNo = 1
  )
  SELECT VALUE(p)
    FROM PurchaseOrder_objtab p
    WHERE p.Cust_Ref.CustNo = 1;

INSERT INTO TABLE (
  SELECT   c.PurchaseOrderList_ntab
    FROM   Customer_objtab c
    WHERE  c.CustNo = 2
  )
  SELECT VALUE(p)
    FROM PurchaseOrder_objtab p
    WHERE p.Cust_Ref.CustNo = 2;

Inserting into Nested Tables

Each of the preceding INSERT statements has two main parts: a TABLE expression that specifies the target table of the insert operation, and a SELECT that gets the data to be inserted. The WHERE clause in each part picks out the customer object to receive the purchase orders (in the TABLE expression) and the customer whose purchase orders are to be selected (in the subquery that gets the purchase orders).

The WHERE clause in the subquery uses dot notation to navigate to the CustNo attribute: p.Cust_Ref.CustNo. Note that a table alias p is required whenever you use dot notation. To omit it and say instead Cust_Ref.CustNo would produce an error.

Another thing to note about the dot notation in this WHERE clause is that we are able to navigate to the CustNo attribute of a customer right through the Cust_Ref REF attribute of a purchase order. SQL (though not PL/SQL) implicitly dereferences a REF used with the dot notation in this way.

The TABLE expression in the first part of the INSERT statement tells the system to treat the collection returned by the expression as a table. The expression is used here to select the nested table of purchase orders for a particular customer as the target of the insert.

In the second part of the INSERT statement, the VALUE() function returns selected rows as objects. In this case, each row is a purchase order object, complete with its own collection of line items. Purchase order rows are selected from one table of type PurchaseOrder_objtyp for insertion into another table of that type.

The preceding INSERT statements use the customer-reference attribute of PurchaseOrder_objtyp to identify the customer to whom each of the existing purchase orders belongs. However, now that all the old purchase orders are copied from the purchase orders table into the upgraded Customer_objtab, this customer-reference attribute of a purchase order is obsolete. Now purchase orders are stored right in the customer object itself.

The following ALTER TYPE statement evolves PurchaseOrder_objtyp to drop the customer-reference attribute. The statement also drops the ShipToAddr_obj attribute as redundant, assuming that the shipping address is always the same as the customer address.

Example A-45 Alter PurchaseOrder_objtyp

ALTER TYPE PurchaseOrder_objtyp
    DROP ATTRIBUTE Cust_ref,
    DROP ATTRIBUTE ShipToAddr_obj
    CASCADE;

This time we were able to use the CASCADE option to let the system perform validations and make all necessary changes to dependent types and tables.

Inserting a New Purchase Order with Line Items

The previous INSERT example showed how to use the VALUE() function to select and insert into the nested table of purchase orders an existing purchase order object complete with its own nested table of line items. The following example shows how to insert a new purchase order that has not already been instantiated as a purchase order object. In this case, the purchase order's nested table of line items must be instantiated, as well as each line item object with its data. Line numbers are shown on the left for reference.

Example A-46 Insert into LineItemList_ntabtyp with VALUE()

INSERT INTO TABLE (                                             /* Line 1  */
  SELECT c.PurchaseOrderList_ntab                               /* Line 2  */
    FROM Customer_objtab c                                      /* Line 3  */
    WHERE c.CustName = 'John Nike'                              /* Line 4  */
   )                                                            /* Line 5  */
  VALUES (1020, SYSDATE, SYSDATE + 1,                           /* Line 6  */
    LineItemList_ntabtyp(                                       /* Line 7  */
      LineItem_objtyp(1, MAKE_REF(Stock_objtab, 1004), 1, 0),   /* Line 8  */
      LineItem_objtyp(2, MAKE_REF(Stock_objtab, 1011), 3, 5),   /* Line 9  */
      LineItem_objtyp(3, MAKE_REF(Stock_objtab, 1535), 2, 10)   /* Line 10 */
      )                                                         /* Line 11 */
);                                                              /* Line 12 */

Lines 1-5 use a TABLE expression to select the nested table to insert into—namely, the nested table of purchase orders for customer John Nike.

The VALUES clause (lines 6-12) contains a value for each attribute of the new purchase order, namely:


PONo
OrderDate
ShipDate
LineItemList_ntab

Line 6 of the INSERT statement specifies values for the three purchase order attributes PONo, OrderDate, and ShipDate.

Only attribute values are given; no purchase order constructor is specified. You do not need to explicitly specify a purchase order constructor to instantiate a purchase order instance in the nested table because the nested table is declared to be a nested table of purchase orders. If you omit a purchase order constructor, the system instantiates a purchase order automatically. You can, however, specify the constructor if you want to, in which case the VALUES clause will look like this:

INSERT INTO TABLE (
  SELECT c.PurchaseOrderList_ntab
    FROM Customer_objtab c
    WHERE c.CustName = 'John Nike'
   )
VALUES (
  PurchaseOrder_objtyp(1025, SYSDATE, SYSDATE + 1,
    LineItemList_ntabtyp(
      LineItem_objtyp(1, MAKE_REF(Stock_objtab, 1004), 1, 0),
      LineItem_objtyp(2, MAKE_REF(Stock_objtab, 1011), 3, 5),
      LineItem_objtyp(3, MAKE_REF(Stock_objtab, 1535), 2, 10)
     )
  )
)

Lines 7-11 instantiate and supply data for a nested table of line items. The constructor method LineItemList_ntabtyp(…) creates an instance of such a nested table that contains three line items.

The line item constructor LineItem_objtyp() creates an object instance for each line item. Values for line item attributes are supplied as arguments to the constructor.

The MAKE_REF function creates a REF for the Stock_ref attribute of a line item. The arguments to MAKE_REF are the name of the stock table and the primary key value of the stock item there that we want to reference. We can use MAKE_REF here because object identifiers in the stock table are based on the primary key: if they were not, we would have to use the REF function in a subquery to get a REF to a row in the stock table.

Querying Multilevel Nested Tables

You can query a top-level nested table column by naming it in the SELECT list like any other top-level (as opposed to embedded) column or attribute, but the result is not very readable. For instance, the following query selects the nested table of purchase orders for John Nike:

Example A-47 Query Customer_objtab for Customer John Nike

SELECT c.PurchaseOrderList_ntab
   FROM Customer_objtab c
   WHERE CustName = 'John Nike';

The query produces a result similar to the following:

PURCHASEORDERLIST_NTAB(PONO, ORDERDATE, SHIPDATE, LINEITEMLIST_NTAB(LINEITEMNO,
--------------------------------------------------------------------------------
PURCHASEORDERLIST_NTABTYP(PURCHASEORDER_OBJTYP(2001, '25-SEP-01', '20-MAY-97', L
INEITEMLIST_NTABTYP(LINEITEM_OBJTYP(10, 00004A038A00468ED552CE6A5803ACE034080020
B8C8340000001426010001000100290000000000090600812A00078401FE0000000B03C20B050000
...

For humans, at least, you probably want to display the instance data in an unnested form and not to show the REFs at all. TABLE expressions—this time in the FROM clause of a query—can help you do this.

For example, the query in Example A-48 selects the PO number, order date, and shipdate for all purchase orders belonging to John Nike:

Example A-48 Query Customer_objtab Using TABLE Expression

SELECT p.PONo, p.OrderDate, p.Shipdate
    FROM Customer_objtab c, TABLE(c.PurchaseOrderList_ntab) p
    WHERE c.CustName = 'John Nike';


PONO ORDERDATE SHIPDATE
------- --------- ---------
2001 25-SEP-01 26-SEP-01
1020 25-SEP-01 26-SEP-01

A TABLE expression takes a collection as an argument and can be used like a SQL table in SQL statements. In the preceding query, listing the nested table of purchase orders in a TABLE expression in the FROM clause enables us to select columns of the nested table just as if they were columns of an ordinary table. The columns are identified as belonging to the nested table by the table alias they use: p. As the example shows, a TABLE expression in the FROM clause can have its own table alias.

Inside the TABLE expression, the nested table is identified as a column of customer table Customer_objtab by the customer table's own table alias c. Note that the table Customer_objtab appears in the FROM clause before the TABLE expression that refers to it. This ability of a TABLE expressions to make use of a table alias that occurs to the left of it in the FROM clause is called left correlation. It enables you to daisy-chain tables and TABLE expressions—including TABLE expressions that make use of the table alias of another TABLE expression. In fact, this is how you are able to select columns of nested tables that are embedded in other nested tables.

Here, for example, is a query that selects information about all line items for PO number 1020:

Example A-49 Query Customer_objtab for Purchase Order 1020

SELECT p.PONo, i.LineItemNo, i.Stock_ref.StockNo, i.Quantity, i.Discount
  FROM Customer_objtab c, TABLE(c.PurchaseOrderList_ntab) p,
    TABLE(p.LineItemList_ntab) i
  WHERE p.PONo = 1020;
 

PONO LINEITEMNO STOCK_REF.STOCKNO QUANTITY DISCOUNT
----- ---------- ----------------- ---------- ----------
1020 1 1004 1 0
1020 2 1011 3 5
1020 3 1535 2 10

The query uses two TABLE expressions, the second referring to the first. Line item information is selected from the inner nested table that belongs to purchase order number 1020 in the outer nested table.

Notice that no column from the customer table occurs in either the SELECT list or the WHERE clause. The customer table is listed in the FROM clause solely to provide a starting point from which to access the nested tables.

Here is a variation on the preceding query. This version shows that you can use the * wildcard to specify all columns of a TABLE expression collection:

SELECT p.PONo, i.*
  FROM Customer_objtab c, TABLE(c.PurchaseOrderList_ntab) p,
    TABLE(p.LineItemList_ntab) i
  WHERE p.PONo = 1020;

Type Inheritance and Substitutable Columns

Suppose that we deal with a lot of our larger, regular customers through an account manager. We would like to add a field for the ID of the account manager to the customer record for these customers.

Earlier, when we wanted to add an attribute for a nested table of purchase orders, we evolved the customer type itself. We could do that again to add an attribute for account manager ID, or we could create a subtype of the customer type and add the attribute only in the subtype. Which should we do?

To make this kind of decision, you need to consider whether the proposed new attribute can be meaningfully and usefully applied to all instances of the base type—to all customers, in other words—or only to an identifiable subclass of the base type.

All customers have purchase orders, so it was appropriate to alter the type itself to add an attribute for them. But not all customers have an account manager; in fact, it happens that only our corporate customers do. So, instead of evolving the customer type to add an attribute that will not be meaningful for customers in general, it makes more sense to create a new subtype for the special kind of customer that we have identified and to add the new attribute there.

Creating a Subtype

You can create a subtype under a base type only if the base type allows subtypes. Whether a type can be subtyped depends on the type's FINAL property. By default, new types are created as FINAL. This means that they are the last of the series and cannot have subtypes created under them. To create a type that can be subtyped, you must specify NOT FINAL in the CREATE TYPE statement as we did when we created the customer type.

You define a subtype by using a CREATE TYPE statement with the UNDER keyword. The following statement creates a new subtype Corp_Customer_objtyp under Customer_objtyp. The type is created as NOT FINAL so that it can have subtypes if we want to add them later.

Example A-50 Create Corp_Customer_objtyp

CREATE TYPE Corp_Customer_objtyp UNDER Customer_objtyp
            (account_mgr_id     NUMBER(6) ) NOT FINAL;
/

When you use a CREATE TYPE statement to create a new subtype, you list only the new attributes and methods that you are adding. The subtype inherits all existing attributes and methods from its base type, so these do not need to be specified. The new attributes and methods are added after the inherited ones. For example, the complete list of attributes for the new Corp_Customer_objtyp subtype looks like this:


CustNo
CustName
Address_obj
Phonelist_var
PurchaseOrderList_ntab
Account_mgr_id

By default, you can store instances of a subtype in any column or object table that is of any base type of the subtype. This ability to store subtype instances in a base type slot is called substitutability. Columns and tables are substitutable unless they have been explicitly declared to be NOT SUBSTITUTABLE. The system automatically adds new columns for subtype attributes and another, hidden column for the type ID of the instance stored in each row.

Actually, it is possible to create a subtype of a FINAL type, but first you must use an ALTER TYPE statement to evolve the type from a FINAL type to a NOT FINAL one. If you want existing columns and tables of the altered type to be able to store instances of new subtypes, specify the CASCADE option CONVERT TO SUBSTITUTABLE in the ALTER TYPE statement. See "Type Evolution".

Inserting Subtypes

If a column or object table is substitutable, you can insert into it not only instances of the declared type of the column or table but also instances of any subtype of the declared type. In the case of table Customer_objtab, this means that the table can be used to store information about all kinds of customers, both ordinary and corporate. However, there is one important difference in the way information is inserted for a subtype: you must explicitly specify the subtype's constructor. Use of the constructor is optional only for instances of the declared type of the column or table.

For example, the following statement inserts a new ordinary customer, William Kidd.

Example A-51 Insert Data for Ordinary Customer

INSERT INTO Customer_objtab
  VALUES (
    3, 'William Kidd',
    Address_objtyp('43 Harbor Drive', 'Redwood Shores', 'CA', '95054'),
    PhoneList_vartyp('415-555-1212'),
    PurchaseOrderList_ntabtyp()
  );

The VALUES clause contains data for each Customer_objtyp attribute but omits the Customer_objtyp constructor. The constructor is optional here because the declared type of the table is Customer_objtyp. For the nested table attribute, the constructor PurchaseOrderList_ntabtyp() creates an empty nested table, but no data is specified for any purchase orders.

Here is a statement that inserts a new corporate customer in the same table. Note the use of the constructor Corp_Customer_objtyp() and the extra data value 531 for the account manager ID:

Example A-52 Insert Data for Corporate Customer

INSERT INTO Customer_objtab
  VALUES (
    Corp_Customer_objtyp(   -- Subtype requires a constructor
      4, 'Edward Teach',
      Address_objtyp('65 Marina Blvd', 'San Francisco', 'CA', '94777'),
      PhoneList_vartyp('415-555-1212', '416-555-1212'),
      PurchaseOrderList_ntabtyp(), 531
    )
  );

The following statements insert a purchase order for each of the two new customers. Unlike the statements that insert the new customers, the two statements that insert purchase orders are structurally the same except for the number of line items in the purchase orders:

Example A-53 Insert Purchase Order for Ordinary Customer

INSERT INTO TABLE (
  SELECT c.PurchaseOrderList_ntab
    FROM Customer_objtab c
    WHERE c.CustName = 'William Kidd'
   )
  VALUES (1021, SYSDATE, SYSDATE + 1,
    LineItemList_ntabtyp(
      LineItem_objtyp(1, MAKE_REF(Stock_objtab, 1535), 2, 10),
      LineItem_objtyp(2, MAKE_REF(Stock_objtab, 1534), 1, 0)
     )
   );

Example A-54 Insert Purchase Order for Corporate Customer

INSERT INTO TABLE (
  SELECT c.PurchaseOrderList_ntab
    FROM Customer_objtab c
    WHERE c.CustName = 'Edward Teach'
   )
  VALUES (1022, SYSDATE, SYSDATE + 1,
    LineItemList_ntabtyp(
      LineItem_objtyp(1, MAKE_REF(Stock_objtab, 1011), 1, 0),
      LineItem_objtyp(2, MAKE_REF(Stock_objtab, 1004), 3, 0),
      LineItem_objtyp(3, MAKE_REF(Stock_objtab, 1534), 2, 0)
     )
   );

Querying Substitutable Columns

A substitutable column or table can contain data of several data types. This enables you, for example, to retrieve information about all kinds of customers with a single query of the customers table. But you can also retrieve information just about a particular kind of customer, or about a particular attribute of a particular kind of customer.

The following examples show some useful techniques for getting the information you want from a substitutable table or column.

The query in Example A-55 uses a WHERE clause that contains an IS OF predicate to filter out customers that are not some kind of corporate customer. In other words, the query returns all kinds of corporate customers but does not return instances of any other kind of customer:

Example A-55 Selecting All Corporate Customers and Their Subtypes

SELECT c.*
  FROM Customer_objtab c
  WHERE VALUE(c) IS OF (Corp_Customer_objtyp);

The query in Example A-56 is similar to the preceding one except that it adds the ONLY keyword in the IS OF predicate to filter out any subtypes of Corp_Customer_objtyp. Rows are returned only for instances whose most specific type is Corp_Customer_objtyp.

Example A-56 Selecting All Corporate Customers with No Subtypes

SELECT p.PONo
  FROM Customer_objtab c, TABLE(c.PurchaseOrderList_ntab) p
  WHERE VALUE(c) IS OF (ONLY Corp_Customer_objtyp);

The query in Example A-57 uses a TABLE expression to get purchase order numbers (from the nested table of purchase orders). Every kind of customer has this attribute, but the WHERE clause confines the search just to corporate customers:

Example A-57 Selecting PONo Just for Corporate Customers

SELECT p.PONo
  FROM Customer_objtab c, TABLE(c.PurchaseOrderList_ntab) p
  WHERE VALUE(c) IS OF (Corp_Customer_objtyp);

The query in Example A-58 returns data for account manager ID. This is an attribute possessed only by the corporate customer subtype: the declared type of the table lacks it. In the query the TREAT() function is used to cause the system to try to regard or treat each customer as a corporate customer in order to access the subtype attribute Account_mgr_id:

Example A-58 Selecting a Subtype Attribute Using the TREAT Function

SELECT CustName, TREAT(VALUE(c) AS Corp_Customer_objtyp).Account_mgr_id
  FROM Customer_objtab c
  WHERE VALUE(c) IS OF (ONLY Corp_Customer_objtyp);

TREAT() is necessary in Example A-58 because Account_mgr_id is not an attribute of the table's declared type Customer_objtyp. If you simply list the attribute in the SELECT list as if it were, a query like the one in Example A-59 will return the error invalid column name error. This is so even with a WHERE clause that excludes all but instances of Corp_Customer_objtyp. The WHERE clause is not enough here because it merely excludes rows from the result.

Example A-59 Selecting a Subtype Attribute Without the TREAT Function

-- Following statement returns error, invalid column name for Account_mgr_id
SELECT CustName, Account_mgr_id
  FROM Customer_objtab c
  WHERE VALUE(c) IS OF (ONLY Corp_Customer_objtyp);

Every substitutable column or object table has an associated hidden type-ID column that identifies the type of the instance in each row. You can look up the type ID of a type in the USER_TYPES catalog view.

The function SYS_TYPEID() returns the type ID of a particular instance. The query in Example A-60 uses SYS_TYPEID() and a join on the USER_TYPES catalog view to return the type name of each customer instance in the table Customer_objtab:

Example A-60 Discovering the Type of Each Instance

SELECT c.CustName, u.TYPE_NAME
  FROM Customer_objtab c, USER_TYPES u
  WHERE SYS_TYPEID(VALUE(c)) = u.TYPEID;


--------------------------------- ---------------------
Jean Nance CUSTOMER_OBJTYP
John Nike CUSTOMER_OBJTYP
William Kidd CUSTOMER_OBJTYP
Edward Teach CORP_CUSTOMER_OBJTYP

For more information on SYS_TYPEID(), VALUE(), and TREAT(), see "Functions and Operators Useful with Objects".

PK#G3PKpUIOEBPS/adobj014.gifGHGIF89a@@@___///oooOOO```000PPP𰰰???!,'xhlp,tmx|VD,ȤrlztJZجvzxL.贺z8|t~znsruyOvqŁEӊخ漿|y~ :c@  ؝Bgqc*u 9!!IrQs(U2aZ^S \ױ冂(h]\1gG_2exXzi`vmyfӢDg 4,x9ބ#GޅʹMS_91e׉{FYMR$u fJLQ(8bh=VB6{!)@ MytqfEce֐pS&DQ/şw)L|!A ΛsD!X@Nu))[3'WD4puO%Z%\z&JH-i嫠y{Sk,jjl3*ᦫMKqv#o7[ '|3 7L cW, 33w +$ !,)2412CZuW1&(vH؊@@|`: mKú]rU ԝʉOS Ŭv=LM>  i d<=̙L6vvJ@j곀`at@GcN8Gb7+0^ H}@OCR<30FG9@@hu1 0n-_l#P;h_11v:CwxH$3!ljSf W&XFhop HQ77t8%"aGEV;@ 8Q@X21 DA1qA쨣 S0}m=6>E6IGу-!I_nVx#pS5d>uqKpsK%.d/u_ѩHh\p"&ќ"2SR X༏VyIjVSd׼pf)6ˮ!BX_gwW7!tˁ)M"3@>Ǎ;۫z-٫4.\`S jxlQ8{D맑 r'KX}d+$*HOk/^bL70l⒀=7}PIa2>!b H0[wFh?:ހMbKSSݧ|q vUWy {#@GTAt{,LtJp0HEՀ@wHHh#a*CGxr\+Hp A y2~ɑL4C g"\<e}FXQFED!apTUp7g4SQPdq*BO5@}3zgou]G ;("&"VGBGBYiGĂOB/1%Ze =TTL4[R‰E$z ^A%uKPHwFChzi~`6bB2~b{t`IY+dcs>1q;6Aq#8f:'EŽx(4N_ud |@(s5,%U8~׸5ܠtW4A5b1%EP @u"e3NjpYsup5y#%N.y= 6rt| G2a2oQbdacS S`C^sMarE*&RU_{ [uޅ&,vcNay=z"d!`1:WJ6zM `X D> 6ɓU8DiX>P%}>?Tr:L#fP#=UQ͑Ph@ 4SAGR@RDxxad\d[ u jH}4Gh;[$GW)-ڋYr*UI,Jz`PrUJÒ\sz4XЫHX*]% At]ąRtU5 =E#P[I$WhAg#hУ 6Z@BTs[aH#Ud#TP"CHKON6I%(XR`_C:@jQ-QNW?XqgR7X|Bn41|d XvCXERQu jG~XyU\eB@ ~?}d([]wQD92䔰Cem;n؊<&SATJ+J6Z@a}y;krHU iyd)tx*Vª}J\",0LKX#S;\݅|XJH J/*woXAŋUIX,[Xz;-:>9S +5R(pKTFahBuƥxA<Ļh_BA[6]C8xYyJU T'Qh ,KAE^^Yo}TJXr7W<S<`gL#1E;} _8NQem^~~mD>$^&~(*,$@04^6~8:<=B>DPHJ6~LP30^@ /^\AWNZbc_ c!SjN~p^)#Fv糦|t~Afj>&锞`~RXg:骎׭^.-kLMɌ)al VM m쮮~>^־Ϯ/G~}n ~A3.> ׾ _O;/nR?"O?&$'O0.1_\6>E0A@B?D_F(0D`PR?Tx8_=\ M_]_^  Ldon$ojuxs#`r/aEc?r`QU^\ V0d'.*#ic#G^N)` ҙUUIVK!!g+BF. RZ̬<j,x6 dd-dtP5mm|fqt (-Pd,p$ 0 ŐƪexB>4qEpBF"ԺUN% `c\te4!AE@,btD6oiS!|tfOD(pAYD$"KJFT*sիDdNj`FkAZD '*yyd5|ӄ"<~in-db@ž O@̰w4J\<ˆY1X OГI޾W'PB-nhR-,xD `Ø !j '<c |X8|B6LqԜ@FX EpL9 PEa| ||3i oEBEcp@1p ᘣ wH$#S&[a lYw Rc(FSV)K/bHC(RrŠ  / O}ȗC'T!4f%4!DzcA JYn` v_n,ȎRoQS6m_[AQ q@QށHI^{dѢ8#=Uq&)p`"(n~W=,0^,?1|h#G\m$~PKB%cgzdc;<\o=>nyI&Bka64x? ~0}G!wxW[y/R"h+oIZXtыbͱ 1#h>>&qWNTh;1z\|?RChc GB2n KF`$%;O2$&KMfc\%+[W deNPiN2%/HJZ,.{ic"3 &3yT>_RҜ&5Cfb J4oSf3in3\gI`4@i{Hg<ޡdIUArAHlIAXt $E^`BЈϏҝe?QS@  M1 ŜD3Lb('O@IE6aܼ J 8r>d0uB@G8&K(8)NЅ$ a.freHɒ* 1u |j q}XAըPW1˂vE$^ ͕v`U4`RȱN[-,oGfUQ+^v ,-P=F+5`Bnw:Rcg% #>xE1 &AK{UVSt:P.x GwxyK_7 Jpi!"*|zl6@ b@ 303n/C0^ic:qeDA^2LJf2',Ԝrl+cYWQ!l39i~79d 0t ?:ЂAC#:ъ^L;9GZ&mJ8҇4+}OJ&]zԠ3YMZVYpZm}Z:5_$$v|ldפb[ԮOB@%?ڑ()a-A5Qo9N\o'D!@KZVgāq>STroÿYy[&潟z@jm] MmB/ Ob3D gl4/H(Oh F P-wya.(kUX!nJ |Xy->X,@U ݖ*;T)jxF2R!((In WMΝ+1b9#GV=Vidʄ ג XΩbBΜ6T9V3U1>@t51HHOLĂ Ԣ,4! bA#@FR ;:VGTE=飫4@{ƇL, t?e=$ dX}ʥU4)Hjyy-WyF,h8"zpXJvœEJNh(bljl>+u,:(ǎ}Φ=Xn\uGP ahM Dl/hP(FWLGPНE Qa÷XBDlbIO]mIg=R8Q ƜMȱx<ԙP[tB~̋ʄ %ޢ۵EǤBUZܱEB©TJQBNV܋NWngL!Ba<@.=(р4 tC|<U8(dH$K4@CT͕M#yC (ĪL`:T@[xF@Md(h% 8A7J(dA+PņUHvHǨ@c8Dc%h0ظSTB}AF[HngH@ /pTۆ &(ܽ 0HH{d6(WۂA[X9KP1G@ýH@SKK|p" t^d9Ϙ X!IA P ܍o8%'{L_yA1J04C C+ LƪX(r_  :ZShaZ "l*خxVG)z Fj`rh2 ϻJ8I ?k@5Ӏp,`Jj䲊DIpJ?@Rh(hIKDը QlU05߄PJOr;3x3 &4@4Chr` c>dttP\Hu gNU|GArjq`,fk#TSuD5|e亱1ȁd` 4Xa F1D0\N(Cz=xR8Ȓ(Foe䴕3 jA kLvLv|e-4s7؀b9vq/1cPrG!r@-hQ$Ȳ~cKM鰛4D t\`7ܐ1NJ8Xt0L|xEnLf q€ ^zIg*$EԆg8 K{EmC_q4wM.V5 -=/$znFzs:z7˾tzl޺z:`z:x\G(%_zs{b[jP.bCĺCWPՆRD*LXI ;;MN<V0QqbNxVq5<ϟ0EL"L {5U) Hc[@[m "w$&\P@}i^D퀝X;aWafM3 ># > ΅t 0Ō;O Ւ͜;{ : h>:iTٴkgi3/g vԦ%\H[7<ҏyzͻ{~%v=yܽފF'eRۿUSG^"T>E|U OV_UiXBTPء}.X!8ȟ!% 5Dۊ0JFN=q!AI꧎oBD!>Vd ŀFǔ$ȈՒcd^ h`!Y0Htew`B0tʘG&5*$0qC#4#@p@I> ,P 񦠋Z(s>! Б@,@h @v) (dCSqdAdRlM+:ѫ _yUᲁXnQ;l-Cqm @V@ Jm26@&<Jb9 ŸX|1\t+4̑Ӯp]kB8ـ !@$,гϷ{;EȢj`GGV-@0` zAZ3Wc7Ws.ON璇DyK]E. -zsKnz\dt`'{x3j `KzMg;h< q0a3 ~Q0@6"t V ]0YLYPAJ"/@/zŌt4p " Vi9ు!1mL$%ɰ @?lrJ.$D2$RB1U!3sqы @aBF H!t| H@dNCC+eAYY! 92=%D@q c(8`+@!EH4  aeB2Z( m4̒Bah%!2?ЂVuw7"oj |@Pya(<&|OBi$4((UxC 0 x YILO OyD %ٕXpIdC-ך$KDl@VL(k'P=xY@ <Ԣr'r5P 4IN Pg?ࠨ?F:<њ"Hh NA0='#ɚ/LbF~7 R;hFGȁP Mf+P!&΂?=FhQT&0^0@\զa]qWRG:YwiHumB2Q\A4hr0M8S'0կ;@ 0ӷ0XjM?m`m6da3/DDɜx6 OۆmBh%!Tuۢ@fЁ cVtI_(F.mdƄsaT6wP0,Vj%GPYE=y (ăr0'A6y EYWĴ _@f(3G*eT7;\!l`Z>`>IYTF?{s\cc+1gcD+1چ ĻAe+%~QwVL1ұ!.PFeBM F,x 6O(I"+(Xb!X-ӛu񽉤'ى̇JUC^DGyz% ‰,Iַ+^ۉ*;Lq=|XHj)DYNo ՑYh^\Uйx.BA_͉sS a-t R02HY_׎sg.zqʞ ^/+v{ܻH4i/+HlZyȋ+w+k~󊯞>=s~o=vI5Z?yS>jǾo_2g_0O8Gg-~/}5KD1e'78WqbgX X{ s 9X6w(X}q}5ﷁP6/8((T<#ҁ,EKu>]L(St1YTWHwQaGrY(g|]6oq(sHuhwy{ȇ}(zikxȈ舏(HXXtȉ艟(!WI芯H~)苿(HHLjȌ?hx1(hBרcP(Hh爎騎Ȏ(H؎xŀZ)Iuև yV ) Ey4!X"q%i /I$ɒ0iF3I y=;=#1Vף*Q=m%GyVs=P<;Nv$b%\kXf3k(TfdoEXt;#>і aQnA>6m5%IR#A$CNK S0ܶ0fCDCIif Va0Ynx~㆙x8v@KgSj/Q!>D%,<A yadZZ=ٜ2u4$g`mC;sD ?nY A$ $CA%[ bPFI 80h4EI 'i%AwʰrCl~$3g0F#Y9pC)&0q%텣  G )AmoI9`Cg%~PFgEj<Dǖ6ڙ:Kǒ)3w@ʨHʀt@rRlF !s,`*p,DAhAl2vQ٫A )lSC3K9D)42~%o8ƀd6Ty@ʮꨑ 'Py*C CF2/ I7:a*Sǵ-I[Aڢ_a7#|bB DAAjqzd2ت5Ăj CUʘJʫ# 3bբWZw:@jv jC3(&Kj `:T ,8rZ:YpL;ꀶS*A `EYz UN  yC(@w:7 2'@+Z^X u fKJj0j*F~YDD'Ķ9KNoG[Y YO{^nK2wc3%)EH䷺CPKP6ҿ;eCdjΆ9$קV٧+S>Z+ 15 p Tt;+x 7guN4< `yDl749`$W@'Q2QFb%m gRB@5P$XӐ$5<-F3‚<xSpj8וP< M;_SU$ a;a@f02k-L#v2EPQ'A*i̓'yt*@@Pɿ>ʷPʯL&(CY˹ |ʺ A˽<"lČƌ<&,UL\rڼs!%S\;1&?BWF+3<E*3-F~Q]b)EPj}&iMS F!q%PM2?_dUTP,}GPEm!"+UVN w˚=a_L: A]7^Ƞ<M 'BIMsMc;qUa) 2t)5U0 -߶#Հɍ(MF q}݂AgHl৓ɑba8\1X[<iy'{'+h|a7΍;B?䩡#^rN!DnFsHJNLNsPR>TVtXZ.\^M'LHjag(, q0eA1F `0?0522-n nmS7N55;lCq>686e#ݲCs3RpҪ%9qi>$Ӛ5gJ9m y=lInϱ"#sb1yS=y6>ee}oӒnmg;Ajbd_Q= 0J\C8d D5)kD&#e5(D& ўȳ oZ"F$LGּ$3i6W6A)eƤ[BDr |VUWQ fF.JNe52: 35U3Au[PoGL)~@5 4KEVۏJ -puu]dY!/뛊gS Ë2 8&q%i љ@Gf ['uޣ?` a!bKIPcUǀAWX IFOh†KBHG% ։'%%AL%M&Ì [M.R&6JQ  9dF6暊 (J„:pX!Ĉ'F (694ŢM j|2`^\`+=p) 4@G88$u B;|0s>\4QE\p+fĚ,jgH 0tSE  #dH0Ċ3R*7LX𬴨) :;5BqmAh~"Zʤd98]{ N; j炵|í?} F/gm?Ix:Y44 L 8 2M3L>jw:+% Y(CG sPg8!A Index

Index

A  B  C  D  E  F  G  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W 

A

Active Server Pages, 4.6
ActiveX, 4.6
ADMIN OPTION
with EXECUTE ANY TYPE, 6.1.3
aggregate functions
See user-defined aggregate functions
aliases
required for tables, 2.1.7.1
ALTER ANY TYPE privilege, 6.1.1
See also privileges
ALTER TABLE, 7.3.6
See also object types, evolving
ALTER TYPE statement, 4.7.5.4, 7.3.5
See also object types, evolving
ANYDATA datatype, 7.4, 8.11.2
ANYDATASET datatype, 7.4
ANYTYPE datatype, 7.4
arrays, A.3.6
size of VARRAYs, 3.1.3
variable (VARRAYs), 3.1.3
ASP, 4.6
assignments
across object types, 2.3.15
collections, 2.3.15.2
objects and REFs to objects, 2.3.15.1
atomic nulls, 2.1.1
attributes
leaf-level, 7.1.1
leaf-level scalar, 7.1.1
modifying, 7.3.3
of object types, 1.3.1.1

B

bind variables
object types, 4.2

C

caches
object cache, 4.3, 4.4, 5.3, 6.1.5
object views, 5.3
capture avoidance rule, 2.1.7.1
CARDINALITY function, 3.2.4.1
CAST function, 2.4.1
character length semantics
object types, 2.1.2
COLLECT function, 3.2.4.2
collections
assigning, 2.3.15.2
comparing, 3.1.10.2, 3.2.3
constructing, 1.3.1.10
creating, 3.1.1
datatypes
DML on, 3.2.2
DML on multilevel, 3.2.2.1
multilevel, 3.1.10, 8.4.1
constructing, 3.1.10.3
creating, 3.1.10.3
creating with REFs, 8.4.5
object views containing, 5.6.2
nested tables, 3.1.4
querying, 3.2.1, 8.4.1
See also varrays, nested tables
substitutable elements, 2.3.8.4
substituting in, 2.3.7
supported datatypes, 1.3.1.10
variable arrays (VARRAYs), 3.1.3
column objects
versus row objects, 8.1.1
COLUMN_VALUE keyword, 3.1.10.1
columns
column objects, 1.3.1.7
hidden, 7.1.3, 7.2.1
indexes on column objects, 2.1.4
qualifying in queries, 2.1.7
qualifying names in queries, 2.1.7.1
comparisons
collections, 2.3.16.1, 3.2.3
methods, 2.2.2, A.3.1, A.3.6.4
object types, 2.3.16.1
REFs, 2.3.16.1
compilation
of object types, 6.2
COMPRESS clause
nested tables, 8.4.4.1
constraints, A.3.4
object tables, 2.1.3
on Oracle objects, 8.8
REFs, 8.3.2
SCOPE FOR constraint, A.3.6.2
constructor methods, 1.3.1.3, 1.3.1.3, 2.2.4, 7.1.2
literal invocation of, 2.2.4
constructors
attribute values, 7.3.7
calling user-defined, 7.3.12
methods, 2.2.4
overloading, 7.3.10
overriding, 7.3.10
system defined, 7.3.7
type evolution, 7.3.8
user-defined, 7.3.9, 7.3.10
with NEW keyword, 7.3.7
COUNT attribute of collection types, A.3.2.2
CREATE ANY TYPE privilege, 6.1.1
See also privileges
CREATE INDEX statement
object types, 2.1.4
CREATE TABLE statement
column object example, 1.3.1.2
object table example, 1.3.1.6
object table examples, 2.1.3
CREATE TRIGGER statement
object table example, 2.1.5
CREATE TYPE privilege, 6.1.1
See also privileges
CREATE TYPE statement, 8.11.4.5
collection types, 1.3.1.10
dependent types, 6.2
example, 3.1.4
nested tables, 3.1.4
object types, 1.3.1.1, 1.3.1.2, A.3.1
varrays, 3.1.3, A.3.1
creating object types, 1.3.1.1
creating VARRAYs
containing references to LOBs, 3.1.9
CURSOR expression, 2.4.2

D

dangling REFs, 1.3.1.9, 1.3.1.9
database administrators (DBAs)
DBA role, 6.1.1
database links
and object types, 2.1.8
datatypes
array types, 3.1.3
nested tables, 3.1.4
See also object types
transient and generic, 7.4
DBA role
user-defined types, 6.1.1
DEFAULT clause, 3.1.2
default values
collections, 3.1.2
object types, 3.1.2
DELETE privilege
for object tables, 6.1.5, 6.1.5
DEREF function, 2.4.3
dereferencing, 1.3.1.9, A.3.2.2
implicit, 1.3.1.9, A.3.2.2
dot notation
using with methods, 2.2.1
DROP ANY TYPE privilege, 6.1.1
See also privileges
DROP TYPE statement, 6.2.3.1
dump files
Export and Import, 6.6
dynamic method dispatch, 2.3.6

E

equal and not equal conditions
nested tables, 3.2.3.1
evolution
object types, 1.3.1.5
Excel, 4.6
EXECUTE ANY TYPE privilege, 6.1.1, 6.1.3
See also privileges
EXECUTE privilege
object types, 6.1.3
See also privileges
Export utility
object types, 6.6
EXTERNAL NAME phrase, 4.7.5

F

features
new, Preface
files
Export and Import dump file, 6.6
FINAL keyword, 2.3.2
modifying finality, 7.3.3, 8.9.3
FORCE keyword, 5.12.2
FORCE option, 6.2.3.1
foreign keys
representing many-to-one entity relationship with, A.2.2.2
function-based indexes
on type methods, 8.5.4

G

GRANT option for EXECUTE privilege, 6.1.3
granting
execute object type, 6.1.3
guidelines
comparison methods, 2.2.2.3

I

implicit dereferencing, 1.3.1.9, A.3.2.2
Import utility
object types, 6.6
IN condition, 3.2.3.2
incomplete object types, 6.2
indexes
nested table, 3.1.4
object types, 2.1.4
on REFs, 2.1.4
type-discriminant column, 7.2.1
index-organized tables
storing nested tables as, 3.1.10.1, 8.4.4.1
inheritance, 1.3.1.4
See type inheritance
inheriting methods, 2.3.5
inner capture, 2.1.7.1
INSERT privilege
for object tables, 6.1.5, 6.1.5
instances
object type, 1.3.1.1
objects, 1.3.1.2
INSTANTIABLE keyword
CREATE TYPE, 2.3.4
modifying instantiability, 7.3.3
INSTEAD OF triggers
nested tables, 5.10.1
invoker-rights
object types, 8.6
IS A SET condition, 3.2.3.6
IS EMPTY condition, 3.2.3.5
IS NOT A SET condition, 3.2.3.6
IS OF type predicate, 2.4.4

J

Java
object storage, 4.7.5
Oracle JDBC and Oracle objects, 4.7.1
Oracle SQLJ and Oracle objects, 4.7.2
with Oracle objects, 4.7
JDBC
See Oracle JDBC
JPublisher, 4.7.4

K

keys
foreign keys, A.2.2.2

L

leaf-level attributes, 7.1.1
scalar, 7.1.1
literal invocation
constructor methods, 2.2.4
locators
returning nested tables as, 7.6.1, 8.4.4.3, 8.4.4.3, A.3.6.2
using a hint, 8.4.4.3
locks
object level locking, 4.3

M

managing
object types, 6
map methods, 8.2, A.3.1, A.3.6.4
comparing collections, 3.2.3.1
for comparing objects, 2.2.2.1
materialized views, 8.7.2
MEMBER condition, 3.2.3.4
member methods, 1.3.1.3, 2.2.1
member procedures
with SELF IN OUT NOCOPY, 8.5.3
methods, A.3.2
choosing a language for, 8.5.1
comparison, A.3.1, A.3.6.4
comparison methods, 2.2.2
in a type hierarchy, 2.2.2.4
constructor, 1.3.1.3
constructor methods, 7.1.2
literal invocation, 2.2.4
constructors, 1.3.1.3, 2.2.4
dot notation, 2.2.1
dropping, 7.3.3
dynamic method dispatch, 2.3.6
execution privilege for, 6.1.2
final, 2.3.2
function-based indexes, 8.5.4
guidelines for comparison, 2.2.2.3
inheriting, 2.3.5
instantiability, 2.3.4
invoking, 2.2.1
map, 2.2.2.1, 8.2, A.3.1, A.3.6.4
map for comparing objects, 2.2.2.1
map required for collections, 3.2.3.1
member, 1.3.1.3, 2.2.1
object types, 1.3.1.3, 2.2
of object types, 1.3.1.1
order, 2.2.2.2, 8.2, A.3.1, A.3.2.3
overloading, 2.3.3, 2.3.5, 2.3.5.1
overriding, 2.3.2, 2.3.3, 2.3.5, 2.3.5.2
PL/SQL, 4.2
redefining, 2.3.5.2
restrictions on overriding, 2.3.5.3
SELF parameter, 2.2.1
static, 1.3.1.3, 2.2.3, 8.5.2
multilevel collections
See collections, multilevel
MULTISET EXCEPT operator, 3.2.4.3
MULTISET INTERSECT operator, 3.2.4.4
multiset operations
with nested tables, 3.2.4
MULTISET UNION operator, 3.2.4.5

N

name resolution
object types, 2.1.7
narrowing, 2.3.15.1, 2.4.8
nested cursor, A.3.6.4
nested tables, 3.1.4, 8.4.4
adding to an object, 7.3.2
COMPRESS clause, 8.4.4.1
creating, 3.1.1
creating indexes on, 8.4.4.2
equal and not equal conditions, 3.2.3.1
in an index-organized table, 3.1.10.1, 8.4.4.1
indexes, 2.1.4, 3.1.4
INSTEAD OF triggers, 5.10.1
multiset operations, 3.2.4
querying, 3.2.1, A.3.1
unnesting results, 3.2.1.2
returning as locators, 8.4.4.3, 8.4.4.3, A.3.6.2
specifying a storage name, 7.3.2
specifying storage in a tablespace, 3.1.5
storage, 3.1.10.1, 8.4.4.1, A.3.6.2
uniqueness in, A.3.6.2
updating in views, 5.10.1
versus VARRAY, A.3.1
versus varrays, A.3.1
NESTED_TABLE_GET_REFS hint, 8.4.4.3
NESTED_TABLE_ID keyword, 3.1.10.1, 8.4.4.2, A.3.6.2
NLS_LENGTH_SEMANTICS initialization parameter, 2.1.2
NOCOPY compiler hint
methods, 2.2.1
performance issues, 8.5.3
use with member procedures, 8.5.3
use with SELF, 2.2.1, 8.5.3
NOT FINAL keyword, 2.3.2
NOT MEMBER condition, 3.2.3.4
nulls
atomic, 2.1.1
object types, 2.1.1

O

object cache
object views, 5.3
OCI, 4.3
privileges, 6.1.5
Pro*C, 4.4
object identifiers, 1.3.1.6, 1.3.1.6, 8.1.2, A.3.5
column and index, 8.1.1.2
for object types, 7.1.2
primary-key based, 8.1.2.1
REFs, 8.1.2
storage, 8.1.2
object instances, 1.3.1.1, 1.3.1.2
<dd class="l2ix">comparing, 2.3.16.1
object tables, 1.3.1.6, 8.1.1.2, A.3.3
constraints, 2.1.3
deleting values, A.3.6.5
indexes, 2.1.4
inserting values, A.3.6.3
querying, A.3.6.4
replicating, 8.7
row objects, 1.3.1.7
triggers, 2.1.5
virtual object tables, 5.1
object types, 1.1
adding a nested table attribute, 7.3.2
advantages, 1.2
altering a type, 7.3.1, 7.3.2
assignments across, 2.3.15
attributes of, 1.3.1.1
character length semantics, 2.1.2
collection objects, 5.6
collections, 3.1
nested tables, 3.1.4
variable arrays (VARRAYs), 3.1.3
column objects, 1.3.1.7
column objects versus row objects, 8.1.1
comparing, 2.3.16.1
comparison methods for, 2.2.2, A.3.1, A.3.6.4
constructor methods, 1.3.1.3
constructor methods for, 2.2.4, 7.1.2
creating, 1.3.1.1, 1.3.1.2
creating subtypes of, 2.3.3
database key features, 1.3.1
dependencies, 6.2
dependents, 6.2, 7.3
evolution, 1.3.1.5
evolving, 7.3, 8.11.1
design considerations, 8.9
SQLJ types, 4.7.5.4
example of privileges, 6.1.4
Export and Import, 6.6
final, 8.9.3
FINAL or NOT FINAL, 2.3.2
in columns, 5.4
incomplete, 6.2, 6.2.1
incomplete types, 6.2
indexes on column objects, 2.1.4
indexing, 7.2.1
inheritance, 1.3.1.4, 2.3
instances, 1.3.1.1
instantiable, 2.3.4
invoker-rights, 8.6
key features, 1.3
locking in cache, 4.3
managing, 6
methods, 2.2, 2.2.1
methods in PL/SQL, 4.2
methods of, 1.3.1.1, A.3.2
mutually dependent, 6.2
name resolution, 2.1.7
nested tables, 3.1.4
not final, 8.9.3
not instantiable, 2.3.4
nulls, 2.1.1
object references, 5.8
Oracle type translator, 4.4.4
performance tuning, 6.4
privileges, 6.1
recompiling, 6.2.2
remote access to, 2.1.8, 5.11
row objects, 1.3.1.7
row objects and object identifiers, 5.6
schema privileges, 6.1.2
See also type inheritance
specializing, 1.3.1.4
SQLJ types, 4.7.5
storage, 7.1
substituting, 2.3.7
subtypes, 2.3.1
synonyms, 6.3
table aliases, 2.1.7.1
tools, 6.5
triggers, 2.1.5
use of table aliases, 2.1.7.1
utilities, 6.6
variable arrays (VARRAYs), 3.1.3
views, 1.3.1.8
object views, 1.3.1.8, 5
advantages of, 5.1
circular references, 5.12.1
defining, 5.2
hierarchies, 5.13, 8.11.3
privileges, 5.13.3
querying in, 5.13.2
modeling relationships, 5.9, 5.12
multilevel collections in, 5.6.2
nested tables, 5.10.1
null objects in, 5.5
OIDs with, 5.7
REFs to, 5.8
replicating, 8.7
updating through INSTEAD OF triggers, 5.10
OBJECT_ID pseudocolumn, 2.3.8.1
OBJECT_VALUE pseudocolumn, 2.3.8.1
object-relational model, A
advantages, 1.2
comparing objects, 8.2
constraints, 8.8
database key features, 1.3.1
design considerations, 8
embedded objects, A.3.6
key features, 1.3
methods, 1.3.1.3, 2.2
partitioning, 7.6
programmatic environments for, 4, 4.7
replication, 8.7
OCCI, 4.5
OCI
associative access, 4.3.1
for Oracle objects
building a program, 4.3.4
navigational access, 4.3.2
object cache, 4.3.3
OCIObjectFlush, 5.3
OCIObjectPin, 5.3
OIDs, 1.3.1.6
See object identifiers
Oracle C++ Call Interface, 4.5
Oracle JDBC
accessing Oracle object data, 4.7.1
Oracle objects
See object-relational model
Oracle Objects for OLE
OraCollection interface, 4.6.3
OraObject interface, 4.6.1
OraRef interface, 4.6.2
support of object-relational features, 4.6
Oracle SQLJ
creating custom Java classes, 4.7.4
data mapping for Oracle objects, 4.7.3
JPublisher, 4.7.4
support for Oracle objects, 4.7.2
Oracle type translator (OTT), 4.4.4
OraCollection interface, 4.6.3
ORAData interface, 4.7.5.1
OraObject interface, 4.6.1
OraRef interface, 4.6.2
order methods, 2.2.2.2, 8.2, A.3.1, A.3.2.3
OTT, 4.4.4
overloading
methods, 2.3.3, 2.3.5.1
user-defined constructors, 7.3.10
overloading methods, 2.3.5
overriding
methods, 2.3.3
user-defined constructors, 7.3.10
overriding methods, 2.3.5

P

parallel query
objects, 8.10
restrictions for Oracle objects, 8.10
view objects, 8.10
partitioning
tables containing Oracle objects, 7.6
pkREFs, 7.1.5
PL/SQL
bind variables
object types, 4.2
object views, 5.3
using with objects, 1.3.1.6
polymorphism, 2.3, 8.11.2, 8.11.3
See also substitutability
POWERMULTISET function, 3.2.4.6
POWERMULTISET_BY_CARDINALITY function, 3.2.4.7
pragma RESTRICT_REFERENCES, A.3.1
primary-key-based REFs, 7.1.5
privileges
acquired by role on object types, 6.1.1
ALTER ANY TYPE on object types, 6.1.1
checked when pinning object types, 6.1.5
column level for object tables, 6.1.5
CREATE ANY TYPE on object types, 6.1.1
DELETE on object types, 6.1.5
DROP ANY TYPE on object types, 6.1.1
EXECUTE ANY TYPE on object types, 6.1.1, 6.1.3
EXECUTE ANY TYPE on object types with ADMIN OPTION, 6.1.3
EXECUTE on object types, 6.1.3
EXECUTE on object types with GRANT option, 6.1.3
INSERT on object types, 6.1.5
object types in types or tables, 6.1.3
object types with CREATE TYPE, 6.1.1
object types with DELETE, 6.1.5
object types with INSERT, 6.1.5
object types with SELECT, 6.1.5
object types with UPDATE, 6.1.5
on object types, 6.1
SELECT on object types, 6.1.5
system on object types, 6.1.1
UNDER ANY TYPE on object types, 6.1.1
UNDER ANY VIEW on object types, 6.1.1
UPDATE on object types, 6.1.5
Pro*C
embedded SQL with user-defined datatypes, 4.4
object cache, 4.4
Pro*C/C++
associative access, 4.4.1
converting between Oracle and C types, 4.4.3
navigational access, 4.4.2
user-defined datatypes, 4.3
programmatic environments
for Oracle objects, 4, 4.7

Q

queries
set membership, 8.4.4.4
unnesting, 8.4.1
varrays, 8.4.3

R

recompilation
object types, 6.2.2
redefining
methods, 2.3.5.2
REF attributes, 2.1.6
REF columns, 2.1.6
REF function, 2.4.5
references, 1.3.1.9
references See REFs
REFs, 1.3.1.9
comparing, 2.3.16.2
constraints on, 2.1.6, 8.3.2
constructing from object identifiers, 7.1.2, A.3.6.3
dangling, 1.3.1.9, 1.3.1.9, 2.1.6
dereferencing of, 1.3.1.9, A.3.2.2
for rows of object views, 5.2
implicit dereferencing of, 1.3.1.9, A.3.2.2
indexes on, 2.1.4
indexing, 8.3.3.1
object identifiers
obtaining, 1.3.1.9
pinning, 5.3, 6.1.5
scoped, 1.3.1.9, 2.1.6, 7.1.5, 8.3.3
size of, 7.1.5
storage, 8.3.1
substitutability, 2.3.7, 2.3.8.3
use of table aliases, 2.1.7.1
WITH ROWID option, 8.3.4
remote databases
using with object types, 2.1.8
RESOURCE role
user-defined types, 6.1.1, 6.1.4
roles
DBA role, 6.1.1
RESOURCE role, 6.1.1, 6.1.4
row objects, 1.3.1.7
storage, 8.1.1.2

S

schemas
object datatypes, 4.2
object types, 1.3.1.1
qualifying column names, 2.1.7.1
SCOPE FOR constraint, A.3.6.2
scoped REFs, 1.3.1.9, 7.1.5
SELECT privilege
for object tables, 6.1.5, 6.1.5
SELF parameter
methods, 2.2.1
SET function, 3.2.4.8
SQL
support for object types, 4.1
user-defined datatypes, 4.1
OCI, 4.3
SQLData interface, 4.7.5.1
SQLJ
See Oracle SQL
SQLJ object types, 4.7, 8.11.4.1
creating, 4.7.5.2
mapping Java classes, 4.7.5.3
See also object types, Oracle SQLJ
static methods, 1.3.1.3, 2.2.3
storage
column objects, 8.1.1.1
nested tables, 7.1.6
object tables, 7.1
REFs, 7.1.5
STORE AS clause, A.3.6.2
SUBMULTISET condition, 3.2.3.3
substitutability, 2.3.7
attributes, 2.3.7
collections, 2.3.7
column and row, 2.3.8, 7.2.1
constraining, 2.3.12
dependencies, 6.2.3
modifying, 2.3.13
narrowing, 2.3.15.1
OBJECT_ID, 2.3.8.1
OBJECT_VALUE, 2.3.8.1
restrictions on modifying, 2.3.14
turning off, 2.3.11
views, 2.3.8
views and, 8.11.3
widening, 2.3.15.1
substitutable columns
dropping subtypes, 2.3.10
subtypes
creating, 2.3.3
dropping in substitutable columns, 2.3.10
hierarchy, 2.3
indexing attributes of, 7.2.2
object types, 2.3.1
specializing, 8.11.1
with supertype attribute, 2.3.8.2
supertypes
attribute of subtype, 2.3.8.2
base in hierarchy, 2.3
synonyms
object types, 6.3
SYS_TYPEID function, 2.4.6, 7.2.1
SYS.ANYDATA, 7.4
SYS.ANYDATASET, 7.4
SYS.ANYTYPE, 7.4
system privileges
ADMIN OPTION, 6.1.3
object types, 6.1.1
See also privileges

T

TABLE
function, 2.4.7
TABLE expressions, 3.2.1.2, 8.4.1
tables
aliases, 2.1.7.1, 2.1.7.1
constraints on object tables, 2.1.3
functions, 2.4.7
indexes on nested tables, 2.1.4
indexes on object tables, 2.1.4
nested tables, 3.1.4
object
See object tables
object tables, 1.3.1.6
virtual, 5.1
qualifying column names, 2.1.7, 2.1.7.1, 2.1.7.1
triggers on object tables, 2.1.5
TREAT function, 2.3.8, 2.3.15.1, 2.4.4, 2.4.8, 7.2.2
triggers
INSTEAD OF triggers
object views and, 5.10
object types, 2.1.5
type dependencies, 6.2.3
type evolution
See object types
type hierarchies, 1.3.1.4, 2.3
methods in, 2.2.2.4
type inheritance
finality, 2.3.2
instantiability, 2.3.4
methods, 2.3.5
object types, 2.3
See inheritance
specializing subtypes, 2.3.1
typeids, 2.4.6, 7.2.1
types
See datatypes, object types

U

UNDER ANY TYPE privilege, 6.1.1
See also privileges
UNDER ANY VIEW privilege, 6.1.1
See also privileges
UNDER keyword
CREATE TYPE, 2.3.3
unnesting queries, 8.4.1
UPDATE privilege
for object tables, 6.1.5, 6.1.5
upd
object views, 5.10
user-defined aggregate functions, 7.5
user-defined constructors, 7.3.9, 7.3.10
user-defined datatypes
See also user-defined types
See object types
user-defined types
and remote databases, 2.1.8
See also object-relational model
See object types
USING clause, 4.7.5

V

validation
failure, 7.3.4
object types, 7.3.3
VALUE function, 2.4.9
variables
bind variables
object types, 4.2
object variables, 5.3
varrays, 3.1.3
accessing, 8.4.3
creating, 3.1.1
creating VARRAYs, 3.1.9
increasing the number of elements, 3.1.8
querying, 8.4.3
See also arrays, collections
storage, 3.1.6, 8.4.2
updating, 8.4.3
versus nested tables, A.3.1, A.3.1
views
object, 1.3.1.8
See also object views
substitutability, 2.3.8
updatability, 5.10
Visual Basic, 4.6

W

widening
and substitutability, 2.3.15.1
PKW  PKpUI OEBPS/rcf.htm Send Us Your Comments

Send Us Your Comments

Oracle Database Application Developer's Guide - Object-Relational Features 10g Release 2 (10.2)

B14260-01

Oracle welcomes your comments and suggestions on the quality and usefulness of this publication. Your input is an important part of the information used for revision.

  • Did you find any errors?

  • Is the information clearly presented?

  • Do you need more information? If so, where?

  • Are the examples correct? Do you need more examples?

  • What features did you like most about this manual?

If you find any errors or have any other suggestions for improvement, please indicate the title and part number of the documentation and the chapter, section, and page number (if available). You can send comments to us in the following ways:

  • Electronic mail: infodev_us@oracle.com

  • FAX: (650) 506-7227. Attn: Server Technologies Documentation Manager

  • Postal service:

    Oracle Corporation
    Server Technologies Documentation Manager
    500 Oracle Parkway, Mailstop 4op11
    Redwood Shores, CA 94065
    USA

If you would like a reply, please give your name, address, telephone number, and electronic mail address (optional).

If you have problems with the software, please contact your local Oracle Support Services.

PK=  PKpUIOEBPS/adobj021.gif\GIF89a}T ///___@@@OOOoooppp```000PPP ???! ,}T@H`H,Ȥrl:ШtJZOvzxL. OgnmP|ymughi±ș^mkoklٔ 澕n  n>$XL HIo7ॄ:`r F*67>Y˗@&m4֬ (xP@=Lv '%K}`gY2?@ar^;Z¨Ul%4ÅJɫ"iC8@Uk)N?=m{Z)[œLL@͛8 @Ú{!ͬn6ײ~[RSMcD*i!c&o]smȷRo?Tzf+`/%5ZjUOjl&h\OyR% \$ FXU xN&%8KQgp'؆@S 1]%^Z̈́N'@b]RQ} ?}50P^'|ͤ֒ESe&lKCVr&Z_P_ Ƹe]waV[]^[[BH`uXc_ d]f*Wk 'ٔTeheV*M M՘& v&l޴إWVӆtIxl=IJXcJn9A%)̫-j\Mq@tRt+miBFtS $E?e\ڕbD{M-mwkMkYDsg#aA*IRQOҖyՌ[kΔCgwpj]ONO :(tQ+jw5i<"%EZRt!"{:4 MU5rmh3FKInZe(~?JSBљU>'ꋢ"อ?9yQ~^(0ār[O؅0lS57h;${ &&D SB8,LgH8ar;h=1_WA*N"A@(ρSA-O}A/c#ɘ P}^qrh3i3v#H? 2!y"2T#II2F&u)$ɕ/?o6N$y`9_ #]2UVS4 W =< 'M4&θM`-`\*LVfx,wA[320`S4%TKfj;s$()Iҡ4(P%2Q=H[BKMLiR&HT"L^&B=5TDCʜgO{Zum3j u epluSegUU|f\mjxY9tO[Nl?ÓYz5vWR)+LmPOaM=e&)Ͳ-V.fLE6ִ̀/ jwV6E,/Ypr-/0R6@o+p=Eb6[4nn7&3u){ҋė2}+>rMWuG8/+7&oy`\tpaaKk:+ݳ΍0fqďE,eLOÇDU f 6qvUFu@ca.Mg'ԬeLY"˘pyy'H+ Ӝ&Z )2'm *(dD'dRAb AkEwJrtS]tZ(%`wF. fT?Qް'Z?t/q]ې!i8B+̆61JcwOȮ&rxjk#լhrX5੷josx wmvdyc}J>f+ + <|MnV<E7g|_3+r[̤]7f_+;yqs|4QX]Nq4+grV $Iӗ>:jO:.%N/$#} 5o뵯tn^aӝF;4}N !z`8vgg:j;LsU B+u 3hJ-(*g;q7[b 7!ZQ*  A1U U, i] _ 158MLb%jk%RL6wACC4[YSpT7ev$02j0j1Ks2XK( K5zdjStKkki:֐42,!D!r++${3* g+B1!(l n 8A^ù 4 $| ?q+Ճ:1{1¼ρ:1!bA(:,h;B K|  `| :4OFC L@n'[dCLJKlqkXĥ {E; ŔwuWD˜T$*8 q< ̲7A,Q\lS^,b\3EƾfW\ vlPz\l00 P:̢HWq(}!Bʢ{ ƫ|dm}ϺMAܯL<=ҔGdzaʞ XȂ0p֠8 :=aKQb UF-z[KMW\S8/}հ@KgΡnbq,t}_l|DkLo=A lȇӃ=YA"<  ` *}΂>m MQK+ c1 `݀L+wظ1s^ g4Η !< M0Z~o1pJj"<9ShhpJtӂ m{怴 i7T,}xww:u]op]L1i+ (p6{k *Ċ]@E"LK h.~!,˝ `)"l$5e˚M ڡ +l-aoԽ#9I3;NNrҠ,\A娠YJ[.:MbIMaCOnqLgON @=Wi؊ _^NwnBŭV.y& w֠֍mMc몤͸zq.A5G+%6m^̶Kǂۭ īS@ndD@hal?ϚٞURrU䢮N>44!ھ. vwθ~A3iN.7.5 34ى|aNZa,5U! d޹3}$^c.ǁD?-I+Ź~#_g9|?S}-j~ʤX>®Yg@KH 1PR}INW!8_O` 8?'d_lIKw܌>~YqA߇n0#q*0~,~5 p8~kpO[ͯu>x oο{Mp~ns} X4Nt>QZ^Y~\6iv 60y< !#%#-/135:>ACEGIKMx=u91`]%TJ!yHbEQ-L,C'9BkaD (@ H:ԙՓF!JպՒJ 8PȔ6 pq*9j`Bȕn]04萫'}DA*&:AP!g1 r6dFּʟw3zΧ7 ukׯaΊ0qֽ;޸Mn/O3|0áUPr.sTYe>t\Wo$1  dē_w `" @H % ϰP+TM5lA^w.Y}EA&āɽZ2ZL͋1Xc&8 QI.QNYYnG>c/'ԇaҲY+Btffř,E~+~:9P|`s>aXKU?bڪiϛ8k{šBJ^hL_ѮR~)}Y,:uV[c"B:`*jtKr@qhƹC/2y?2%aR@}1VwԁyO[r| _~ʊ67_!݃Yuۓ?gވ`.k?+W?G9α:6ONx -Ad61 1@YA';ANJ<D htEKKaSΔV!VR i=OA)QAf:FOj2Fm(HtԤf`N%Ѱhd7&uT8*lu$IU+kjoeǢ9R5jO:3ȼ ]gBMOܳ'N> Ś4r},dT˻JB5Yf,j=(%<$vel<<Ζ{]-&,$M\**ˍ|[\@ յuQ,lѕ?ĭJ&Q4O<*B#S-%H߿3->Z XKQ^E.4$ M턻X\D  L;Xjť DXl x Z*DfvȮ/WQVc G#ɲ.|(VY Sj8,(5mvg9ϙu=}, ;PKpyPKpUIOEBPS/blafdoc.cssF/* blafdoc.css */ /* Release 1.1.0 */ /* Copyright 2002, 2003 Oracle. All rights reserved. */ /* ========================================================================== */ BODY { font-family : Arial, Helvetica, Geneva, sans-serif; background-color : #FFFFFF; color : #000000; } BODY, P, TABLE, TD, TH, OL, UL, A, DL, DT, DD, BLOCKQUOTE, CAPTION { font-family : Arial, Helvetica, Geneva, sans-serif; font-size : small; } A:link { color : #663300; background-color : #FFFFFF; } A:active { color:#ff6600; background-color : #FFFFFF; } A:visited { color:#996633; background-color : #FFFFFF; } A.glossary-link { border-bottom : 1px dotted; text-decoration : none; } H1, H2, H3, H4 { font-family: Arial, Helvetica, Geneva, sans-serif; color: #336699; background-color : #FFFFFF; } H1 { font-size : 1.6em; font-weight: bold; border : solid #CCCC99; border-width : 0px 0px 1px 0px; width : 100%; } H2 { font-size:1.3em; font-weight: bold; } H3 { font-size:1.1em; font-weight: bold; } H4 { font-size:1em; font-weight: normal; } H1 A, H2 A, H3 A, H4 A { font-size: 100%; } PRE, CODE { font-family: Courier, "Courier New", monospace; font-size:1em; } CODE { color: #336699; } CODE .code-comment { color: #000000; } H1 A CODE, H2 A CODE, H3 A CODE, H4 A CODE { color: #336699; font-weight: bold; } A:link CODE { color: #663300; } A:active CODE { color: #ff6600; } A:visited CODE { color: #996633; } TABLE { font-size: small; } CAPTION { text-align : center; font-weight : bold; width: auto; } TD { vertical-align : top; } TH { font-weight: bold; text-align: left; vertical-align : bottom; color: #336699; background-color: #FFFFFF; } TABLE.table-border { border : 1px solid #CCCC99; } TABLE.table-border TD, TABLE.table-border TH { padding : 2px 4px 2px 4px; background-color: #FFFFFF; border : 1px solid #CCCC99; } TABLE.table-border TH.table-header-border-left, TABLE.table-border TH.table-header-border-middle, TABLE.table-border TH.table-header-border-right { background-color: #cccc99; color: #336699; } TABLE.table-border TH.table-header-border-left { border-left : 1px solid #CCCC99; border-right : 1px solid #FFFFFF; background-color: #cccc99; } TABLE.table-border TH.table-header-border-middle { border-left : 1px solid #FFFFFF; border-right : 1px solid #FFFFFF; background-color: #cccc99; } TABLE.table-border TH.table-header-border-right { border-left : 1px solid #FFFFFF; border-right : 1px solid #CCCC99; background-color: #cccc99; } SPAN.gui-object { font-weight: bold; } P.horizontal-rule { width : 100%; border : solid #CCCC99; border-width : 0px 0px 1px 0px; margin-bottom : 2em; } div.zz-skip-header { margin-bottom : 0px; margin-top : -2px; padding : 0px; text-align:center; line-height : 1px; } div.zz-skip-header a:link, div.zz-skip-header a:visited, div.zz-skip-header a:active { color:white; background-color:white; text-decoration:none; font-size:.1em; line-height : 1px; } TD.zz-nav-header-cell { text-align : left; font-size : small; width : 99%; color:#000000; background-color : #FFFFFF; font-weight : normal; vertical-align : top; margin-top : 0px; padding-top : 0px; } A.zz-nav-header-link { font-size : small; } TD.zz-nav-button-cell { text-align : center; width : 1%; vertical-align : top; padding-left : 4px; padding-right : 4px; margin-top : 0px; padding-top : 0px; } A.zz-nav-button-link { font-size : x-small; } DIV.zz-nav-footer-menu { width : 100%; text-align : center; margin-top : 1em; margin-bottom : 2em; } P.zz-legal-notice, A.zz-legal-notice-link { font-size : xx-small; /* display : none ; */ /* Uncomment this to hide the legal notice */ } PKs!PKpUIOEBPS/adobj028.gif GIF89a;忿???999@@@ϟ///___oooOOO``` 000ppp>>>ddd:::<<<!*,;UH*\ȰÇ 1Hŋ3jȱǏ1@Iɓ(S,i˗0cʜI͛8sꬉ`ϟ@ :H*]ʴӧPJJ逞DjѪ`ÊK֪#]˶eʝ[v@ 7%\ VjoÈ;㱅*LY/ǘ3?\筗5+C^4װfMظs]wݻu [f0OD@`@X|)KX | ߙh »6J`YA  0T8045_}d' x8`bbӅRs1!u`R`Rx!258@)tBTcUQ ~a'@@AH@%5BH@_u%U0f 4@4\s`:@p r*@y*rRl X @R4icSPT~ݷTHe`OB'm.kI-a^_n+.U~k.Cَk綻XkU֫PƮ/kۮk' 7 @Pw ,$l`X,@0,4l8<\,_DmH'L7I_ԕ 5Xg=h_ͯ.e`Hlmx6L wV]4`apq׌WNK[9nngauN错ꇩn]NDَ?(# O'7c Wo·pV;u/Lo?觯9o~P.QKSoȿ_0%ί ā`ƾz}DH>Ho10 gH0bVx@ b הBx+_W/0Lܗ08KⶤE-ʊ?M9E4ˌFqs"UGqYcBȱ|ٛC΁nI8R  *@",U$A)Xtc%K" ) &3QQ@M $<` ʢd)Ցd j&RgLҺͤ,@%0N֤* R L=Et0gaϸ),V^&S.6GhMPcʔSI!ӕT,ayKKqK?7M|f˞qr%25Wqv첛5ϙ)h̭鶕Ϙse h4Y΅SDO͎.HЖ̢'B!zӠPԨ֚ Y8AaMZz^[`>uf;†HMj{̶2@6mОmw>ș Ltٹ%7f=8}n4)owps9oWn,|x 8".qQ⸻8iîgCt&?9Rr$09 Gݶfo\7FNHOҗFs.uQ꛻:-3^70hOW@H[xϻ<@#`K~'^J(P_?^wQ b7H=H͇^'=7`Ч^a)L7zWEG=mܟq$Ucr7w=_¤W6p,e V'HSiUvO.WlJNT(4]9! I2`S$w[C~?%|R QJ`bz7z`"@!]0 YG|fR]\ 0*)UU -e&$! [gfKW$ rQq^ 8{#;#v}a&Ph]%$@!äVN&c$&U5VLhX$$ƄG{]R}%!o"J2bW!'!%p PLّbLE&!!$XV^)*w'0Ext(Gt,t)K`TY&GGJX(Q( 7LzbV 艌|!}I Tr}ʗi (eqXTJ}F}hШ(_{㸍{8wȘFd׎ȍ{s1؏i02 2@gm9=s;PK&̈ PKpUIOEBPS/adobjvew.htm Applying an Object Model to Relational Data

5 Applying an Object Model to Relational Data

This chapter shows how to write object-oriented applications without changing the underlying structure of your relational data.

The chapter contains these topics:

Why Use Object Views

Just as a view is a virtual table, an object view is a virtual object table. Each row in the view is an object: you can call its methods, access its attributes using the dot notation, and create a REF that points to it.

Object views are useful in prototyping or transitioning to object-oriented applications because the data in the view can be taken from relational tables and accessed as if the table were defined as an object table. You can run object-oriented applications without converting existing tables to a different physical structure.

Object views can be used like relational views to present only the data that you want users to see. For example, you might create an object view that presents selected data from an employee table but omits sensitive data about salaries.

Using object views can lead to better performance. Relational data that make up a row of an object view traverse the network as a unit, potentially saving many round trips.

You can fetch relational data into the client-side object cache and map it into C structures or C++ or Java classes, so 3GL applications can manipulate it just like native classes. You can also use object-oriented features like complex object retrieval with relational data.

  • By synthesizing objects from relational data, you can query the data in new ways. You can view data from multiple tables by using object de-referencing instead of writing complex joins with multiple tables.

  • Because the objects in the view are processed within the server, not on the client, this can result in significantly fewer SQL statements and much less network traffic.

  • The object data from object views can be pinned and used in the client side object cache. When you retrieve these synthesized objects in the object cache by means of specialized object-retrieval mechanisms, you reduce network traffic.

  • You gain great flexibility when you create an object model within a view in that you can continue to develop the model. If you need to alter an object type, you can simply replace the invalidated views with a new definition.

  • Using objects in views does not place any restrictions on the characteristics of the underlying storage mechanisms. By the same token, you are not limited by the restrictions of current technology. For example, you can synthesize objects from relational tables which are parallelized and partitioned.

  • You can create different complex data models from the same underlying data.


    See Also:


Defining Object Views

The procedure for defining an object view is:

  1. Define an object type, where each attribute of the type corresponds to an existing column in a relational table.

  2. Write a query that specifies how to extract the data from relational tables. Specify the columns in the same order as the attributes in the object type.

  3. Specify a unique value, based on attributes of the underlying data, to serve as an object identifier, which enables you to create pointers (REFs) to the objects in the view. You can often use an existing primary key.

If you want to be able to update an object view, you may have to take another step, if the attributes of the object type do not correspond exactly to columns in existing tables:

Write an INSTEAD OF trigger procedure for Oracle to execute whenever an application program tries to update data in the object view. See "Updating Object Views".

After these steps, you can use an object view just like an object table.

For example, the following SQL statements define an object view, where each row in the view is an object of type employee_t:

Example 5-1 Creating an Object View

CREATE TABLE emp_table (
    empnum   NUMBER (5),
    ename    VARCHAR2 (20),
    salary   NUMBER (9,2),
    job      VARCHAR2 (20));

CREATE TYPE employee_t AS OBJECT (
    empno    NUMBER (5),
    ename    VARCHAR2 (20),
    salary   NUMBER (9,2),
    job      VARCHAR2 (20));
/

CREATE VIEW emp_view1 OF employee_t
    WITH OBJECT IDENTIFIER (empno) AS
        SELECT e.empnum, e.ename, e.salary, e.job
            FROM emp_table e
            WHERE job = 'Developer';

To access the data from the empnum column of the relational table, you would access the empno attribute of the object type.

Using Object Views in Applications

Data in the rows of an object view may come from more than one table, but the object still traverses the network in one operation. The instance appears in the client side object cache as a C or C++ structure or as a PL/SQL object variable. You can manipulate it like any other native structure.

You can refer to object views in SQL statements in the same way you refer to an object table. For example, object views can appear in a SELECT list, in an UPDATE-SET clause, or in a WHERE clause.

You can also define object views on object views.

You can access object view data on the client side using the same OCI calls you use for objects from object tables. For example, you can use OCIObjectPin() for pinning a REF and OCIObjectFlush() for flushing an object to the server. When you update or flush to the server an object in an object view, Oracle updates the object view.


See Also:

See Oracle Call Interface Programmer's Guide for more information about OCI calls.

Nesting Objects in Object Views

An object type can have other object types nested in it as attributes.

If the object type on which an object view is based has an attribute that itself is an object type, then you must provide column objects for this attribute as part of the process of creating the object view. If column objects of the attribute type already exist in a relational table, you can simply select them; otherwise, you must synthesize the object instances from underlying relational data just as you synthesize the principal object instances of the view. You synthesize, or create, these objects by calling the respective object type's constructor method to create the object instances, and you populate their attributes with data from relational columns that you specify in the constructor.

For example, consider the department table dept in Example 5-2. You might want to create an object view where the addresses are objects inside the department objects. That would allow you to define reusable methods for address objects, and use them for all kinds of addresses.

First, create the types for the address and department objects, then create the view containing the department number, name and address. The address objects are constructed from columns of the relational table.

Example 5-2 Creating a View with Nested Object Types

CREATE TABLE dept (
    deptno       NUMBER PRIMARY KEY,
    deptname     VARCHAR2(20),
    deptstreet   VARCHAR2(20),
    deptcity     VARCHAR2(10),
    deptstate    CHAR(2),
    deptzip      VARCHAR2(10));

CREATE TYPE address_t AS OBJECT (
   street   VARCHAR2(20),
    city    VARCHAR2(10),
    state   CHAR(2),
    zip     VARCHAR2(10));
/
CREATE TYPE dept_t AS OBJECT (
   deptno     NUMBER,
   deptname   VARCHAR2(20),
   address    address_t );
/

CREATE VIEW dept_view OF dept_t WITH OBJECT IDENTIFIER (deptno) AS
    SELECT d.deptno, d.deptname,
      address_t(d.deptstreet,d.deptcity,d.deptstate,d.deptzip) AS 
      deptaddr
      FROM dept d;

Identifying Null Objects in Object Views

Because the constructor for an object never returns a null, none of the address objects in the preceding view can ever be null, even if the city, street, and so on columns in the relational table are all null. The relational table has no column that specifies whether the department address is null. If we define a convention so that a null deptstreet column indicates that the whole address is null, then we can capture the logic using the DECODE function, or some other function, to return either a null or the constructed object:

Example 5-3 Identifying Null Objects in an Object View

CREATE OR REPLACE VIEW dept_view AS
  SELECT d.deptno, d.deptname,
        DECODE(d.deptstreet, NULL, NULL, 
        address_t(d.deptstreet, d.deptcity, d.deptstate, d.deptzip)) AS deptaddr
  FROM dept d;

Using such a technique makes it impossible to directly update the department address through the view, because it does not correspond directly to a column in the relational table. Instead, we would define an INSTEAD OF trigger over the view to handle updates to this column.

Using Nested Tables and Varrays in Object Views

Collections, both nested tables and VARRAYs, can be columns in views. You can select these collections from underlying collection columns or you can synthesize them using subqueries. The CAST-MULTISET operator provides a way of synthesizing such collections.

Single-Level Collections in Object Views

Using Example 5-2 as our starting point, we represent each employee in an emp relational table that has the following structure in Example 5-4. Using this relational table, we can construct a dept_view with the department number, name, address and a collection of employees belonging to the department.

First, define a nested table type for the employee type employee_t. Next, define a department type having a department number, name, address, and a nested table of employees. Finally, define the object view dept_view.

Example 5-4 Creating a View with a Single-Level Collection

CREATE TABLE emp (
   empno    NUMBER PRIMARY KEY,
   empname  VARCHAR2(20),
   salary   NUMBER,
   job      VARCHAR2 (20), 
   deptno   NUMBER REFERENCES dept(deptno));

CREATE TYPE employee_list_t AS TABLE OF employee_t;
/
CREATE TYPE dept_t AS OBJECT (
    deptno     NUMBER,
    deptname   VARCHAR2(20),
    address    address_t,
    emp_list   employee_list_t);
/
CREATE VIEW dept_view OF dept_t WITH OBJECT IDENTIFIER (deptno) AS
    SELECT d.deptno, d.deptname,
     address_t(d.deptstreet,d.deptcity,d.deptstate,d.deptzip) AS deptaddr,
             CAST( MULTISET (
                           SELECT e.empno, e.empname, e.salary, e.job
                           FROM emp e 
                           WHERE e.deptno = d.deptno) 
                        AS employee_list_t)
                   AS emp_list
   FROM dept d;

The SELECT subquery inside the CAST-MULTISET block selects the list of employees that belong to the current department. The MULTISET keyword indicates that this is a list as opposed to a singleton value. The CAST operator casts the result set into the appropriate type, in this case to the employee_list_t nested table type.

A query on this view could give us the list of departments, with each department row containing the department number, name, the address object and a collection of employees belonging to the department.

Multilevel Collections in Object Views

Multilevel collections and single-level collections are created and used in object views in the same way. The only difference is that, for a multilevel collection, you must create an additional level of collections.

Example 5-5 builds an object view containing a multilevel collection. The view is based on flat relational tables that contain no collections. As a preliminary to building the object view, the example creates the object and collection types it uses. An object type (for example, emp_t) is defined to correspond to each relational table, with attributes whose types correspond to the types of the respective table columns. In addition, the employee type has a nested table (attribute) of projects, and the department type has a nested table (attribute) of employees. The latter nested table is a multilevel collection. The CAST-MULTISET operator is used in the CREATE VIEW statement to build the collections.

Example 5-5 Creating a View with Multilevel Collections

CREATE TABLE depts
  ( deptno     NUMBER,
    deptname   VARCHAR2(20));

CREATE TABLE emps
  ( ename VARCHAR2(20),
    salary     NUMBER,
    deptname   VARCHAR2(20));

CREATE TABLE projects
  ( projname   VARCHAR2(20),
    mgr        VARCHAR2(20));

CREATE TYPE project_t AS OBJECT
  ( projname   VARCHAR2(20),
    mgr        VARCHAR2(20));
/
CREATE TYPE nt_project_t AS TABLE OF project_t;
/
CREATE TYPE emp_t AS OBJECT
(  ename      VARCHAR2(20),
   salary     NUMBER,
   deptname   VARCHAR2(20),
   projects   nt_project_t );
/
CREATE TYPE nt_emp_t AS TABLE OF emp_t;
/
CREATE TYPE depts_t AS OBJECT
  ( deptno     NUMBER,
    deptname   VARCHAR2(20),
    emps       nt_emp_t );
/
CREATE VIEW v_depts OF depts_t WITH OBJECT IDENTIFIER (deptno) AS
  SELECT d.deptno, d.deptname, 
    CAST(MULTISET(SELECT e.ename, e.salary, e.deptname,
        CAST(MULTISET(SELECT p.projname, p.mgr
          FROM projects p
          WHERE p.mgr = e.ename)
        AS nt_project_t)
      FROM emps e
      WHERE e.deptname = d.deptname)
    AS nt_emp_t)
  FROM depts d;

Specifying Object Identifiers for Object Views

You can construct pointers (REFs) to the row objects in an object view. Because the view data is not stored persistently, you must specify a set of distinct values to be used as object identifiers. The notion of object identifiers allows the objects in object views to be referenced and pinned in the object cache.

If the view is based on an object table or an object view, then there is already an object identifier associated with each row and you can reuse them. Either omit the WITH OBJECT IDENTIFIER clause, or specify WITH OBJECT IDENTIFIER DEFAULT.

However, if the row object is synthesized from relational data, you must choose some other set of values.

Oracle lets you specify object identifiers based on the primary key. The set of unique keys that identify the row object is turned into an identifier for the object. These values must be unique within the rows selected out of the view, because duplicates would lead to problems during navigation through object references.

The object view created with the WITH OBJECT IDENTIFIER clause has an object identifier derived from the primary key. If the WITH OBJECT IDENTIFIER DEFAULT clause is specified, the object identifier is either system generated or primary key based, depending on the underlying table or view definition.

For example, note the definition of the object type dept_t and the object view dept_view described in "Single-Level Collections in Object Views".

Because the underlying relational table has deptno as the primary key, each department row has a unique department number. In the view, the deptno column becomes the deptno attribute of the object type. Once we know that deptno is unique within the view objects, we can specify it as the object identifier.

See "Storage Considerations for Object Identifiers (OIDs)".

Creating References to View Objects

In the example we have been developing, each object selected out of the dept_view view has a unique object identifier derived from the department number value. In the relational case, the foreign key deptno in the emp employee table matches the deptno primary key value in the dept department table. We used the primary key value for creating the object identifier in the dept_view. This allows us to use the foreign key value in the emp_view in creating a reference to the primary key value in dept_view.

We accomplish this by using MAKE_REF operator to synthesize a primary key object reference. This takes the view or table name to which the reference points and a list of foreign key values to create the object identifier portion of the reference that will match with a particular object in the referenced view.

In order to create an emp_view view which has the employee's number, name, salary and a reference to the department in which she works, we need first to create the employee type emp_t and then the view based on that type as shown in Example 5-6.

Example 5-6 Creating a Reference to Objects in a View

CREATE TYPE emp_t AS OBJECT (
  empno    NUMBER,
  ename    VARCHAR2(20),
  salary   NUMBER,
  deptref  REF dept_t);
/
CREATE OR REPLACE VIEW emp_view OF emp_t WITH OBJECT IDENTIFIER(empno)
   AS SELECT e.empno, e.empname, e.salary, 
                      MAKE_REF(dept_view, e.deptno) 
         FROM emp e;

The deptref column in the view holds the department reference. The following simple query retrieves all employees whose department is located in the city of San Francisco:

SELECT e.empno, e.salary, e.deptref.deptno
  FROM emp_view e
 WHERE e.deptref.address.city = 'San Francisco';

Note that we could also have used the REF modifier to get the reference to the dept_view objects:

CREATE OR REPLACE VIEW emp_view OF emp_t WITH OBJECT IDENTIFIER(empno)
   AS SELECT e.empno, e.empname, e.salary, REF(d)
         FROM emp e, dept_view d
          WHERE e.deptno = d.deptno;

In this case we join the dept_view and the emp table on the deptno key. The advantage of using MAKE_REF operator instead of the REF modifier is that in using the former, we can create circular references. For example, we can create employee view to have a reference to the department in which she works, and the department view can have a list of references to the employees who work in that department.

Note that if the object view has a primary key based object identifier, the reference to such a view is primary key based. On the other hand, a reference to a view with system generated object identifier will be a system generated object reference. This difference is only relevant when you create object instances in the OCI object cache and need to get the reference to the newly created objects. This is explained in a later section.

As with synthesized objects, we can also select persistently stored references as view columns and use them seamlessly in queries. However, the object references to view objects cannot be stored persistently.

Modelling Inverse Relationships with Object Views

Views with objects can be used to model inverse relationships.

One-to-One Relationships

One-to-one relationships can be modeled with inverse object references. For example, let us say that each employee has a particular computer on her desk, and that the computer belongs to that employee only. A relational model would capture this using foreign keys either from the computer table to the employee table, or in the reverse direction. Using views, we can model the objects so that we have an object reference from the employee to the computer object and also have a reference from the computer object to the employee.

One-to-Many and Many-to-One Relationships

One-to-many relationships (or many-to-many relationships) can be modeled either by using object references or by embedding the objects. One-to-many relationship can be modeled by having a collection of objects or object references. The many-to-one side of the relationship can be modeled using object references.

Consider the department-employee case. In the underlying relational model, we have the foreign key in the employee table. Using collections in views, we can model the relationship between departments and employees. The department view can have a collection of employees, and the employee view can have a reference to the department (or inline the department values). This gives us both the forward relation (from employee to department) and the inverse relation (department to list of employees). The department view can also have a collection of references to employee objects instead of embedding the employee objects.

Updating Object Views

You can update, insert, and delete data in an object view using the same SQL DML you use for object tables. Oracle updates the base tables of the object view if there is no ambiguity.

A view is not directly updatable if its view query contains joins, set operators, aggregate functions, or GROUP BY or DISTINCT clauses. Also, individual columns of a view are not directly updatable if they are based on pseudocolumns or expression in the view query.

If a view is not directly updatable, you can still update it indirectly using INSTEAD OF triggers. To do so, you define an INSTEAD OF trigger for each kind of DML statement you want to execute on the view. In the INSTEAD OF trigger, you code the operations that must take place on the underlying tables of the view to accomplish the desired change in the view. Then, when you issue a DML statement for which you have defined an INSTEAD OF trigger, Oracle transparently runs the associated trigger. See "Using INSTEAD OF Triggers to Control Mutating and Validation" for an example of an INSTEAD OF trigger.

Something you want to be careful of: In an object view hierarchy, UPDATE and DELETE statements operate polymorphically just as SELECT statements do: the set of rows picked out by an UPDATE or DELETE statement on a view implicitly includes qualifying rows in any subviews of the specified view as well. See "Object View Hierarchies" for a discussion of object view hierarchy and examples defining Student_v and Employee_v.

For example, the following statement, which deletes all persons from Person_v, also deletes all students from Student_v and all employees from the Employee_v view.

DELETE FROM Person_v;

To exclude subviews and restrict the affected rows just to those in the view actually specified, use the ONLY keyword. For example, the following statement updates only persons and not employees or students.

UPDATE ONLY(Person_v) SET address = ...

Updating Nested Table Columns in Views

A nested table can be modified by inserting new elements and updating or deleting existing elements. Nested table columns that are virtual or synthesized, as in a view, are not usually updatable. To overcome this, Oracle allows INSTEAD OF triggers to be created on these columns.

The INSTEAD OF trigger defined on a nested table column (of a view) is fired when the column is modified. Note that if the entire collection is replaced (by an update of the parent row), the INSTEAD OF trigger on the nested table column is not fired.

Using INSTEAD OF Triggers to Control Mutating and Validation

INSTEAD OF triggers provide a way of updating complex views that otherwise could not be updated. They can also be used to enforce constraints, check privileges and validate the DML. Using these triggers, you can control mutation of the objects created though an object view that might be caused by inserting, updating and deleting.

For instance, suppose we wanted to enforce the condition that the number of employees in a department cannot exceed 10. To enforce this, we can write an INSTEAD OF trigger for the employee view. The trigger is not needed for doing the DML because the view can be updated, but we need it to enforce the constraint.

We implement the trigger by means of the SQL statements in Example 5-7.

Example 5-7 Creating INSTEAD OF Triggers on a View

CREATE TRIGGER emp_instr INSTEAD OF INSERT on emp_view 
FOR EACH ROW
DECLARE
  dept_var dept_t;
  emp_count integer;
BEGIN
  -- Enforce the constraint
  -- First get the department number from the reference
  UTL_REF.SELECT_OBJECT(:NEW.deptref, dept_var);

  SELECT COUNT(*) INTO emp_count
    FROM emp
   WHERE deptno = dept_var.deptno;
  IF emp_count < 9 THEN
     -- Do the insert
     INSERT INTO emp (empno, empname, salary, deptno) 
        VALUES (:NEW.empno, :NEW.ename, :NEW.salary, dept_var.deptno);
  END IF;
END;
/

Applying the Object Model to Remote Tables

Although you cannot directly access remote tables as object tables, object views let you access remote tables as if they were object tables.

Consider a company with two branches; one in Washington D.C. and another in Chicago. Each site has an employee table. The headquarters in Washington has a department table with the list of all the departments. To get a total view of the entire organization, we can create views over the individual remote tables and then a overall view of the organization.

In Example 5-8, we begin by creating an object view for each employee table. Then we can create the global view.

Example 5-8 Creating an Object View to Access Remote Tables

CREATE VIEW emp_washington_view (eno, ename, salary, job)
   AS SELECT e.empno, e.empname, e.salary, e.job
          FROM emp@washington e;

CREATE VIEW emp_chicago_view (eno, ename, salary, job)
   AS SELECT e.empno, e.empname, e.salary, e.job
          FROM emp@chicago e;

CREATE VIEW orgnzn_view OF dept_t WITH OBJECT IDENTIFIER (deptno) 
    AS SELECT d.deptno, d.deptname,
          address_t(d.deptstreet,d.deptcity,d.deptstate,d.deptzip) AS deptaddr,
          CAST( MULTISET (
                      SELECT e.eno, e.ename, e.salary, e.job
                      FROM emp_washington_view e) 
                   AS employee_list_t) AS emp_list
       FROM dept d
       WHERE d.deptcity = 'Washington'
   UNION ALL
       SELECT d.deptno, d.deptname,
           address_t(d.deptstreet,d.deptcity,d.deptstate,d.deptzip) AS deptaddr,
              CAST( MULTISET (
                       SELECT e.eno, e.ename, e.salary, e.job
                       FROM emp_chicago_view e) 
                    AS employee_list_t) AS emp_list
       FROM dept d
       WHERE d.deptcity = 'Chicago';

This view has the list of all employees for each department. We use UNION ALL because we cannot have two employees working in more than one department.

Defining Complex Relationships in Object Views

You can define circular references in object views using the MAKE_REF operator: view_A can refer to view_B which in turn can refer to view_A. This allows an object view to synthesize a complex structure such as a graph from relational data.

For example, in the case of the department and employee, the department object currently includes a list of employees. To conserve space, we may want to put references to the employee objects inside the department object, instead of materializing all the employees within the department object. We can construct (pin) the references to employee objects, and later follow the references using the dot notation to extract employee information.

Because the employee object already has a reference to the department in which the employee works, an object view over this model contains circular references between the department view and the employee view.

You can create circular references between object views in two different ways:

Method 2 has fewer steps, but the FORCE keyword may hide errors in the view creation. You need to query the USER_ERRORS catalog view to see if there were any errors during the view creation. Use this method only if you are sure that there are no errors in the view creation statement.

Also, if errors prevent the views from being recompiled upon use, you must recompile them manually using the ALTER VIEW COMPILE command.

We will see the implementation for both the methods.

Tables and Types to Demonstrate Circular View References

First, we set up some relational tables and associated object types. Although the tables contain some objects, they are not object tables. To access the data objects, we will create object views later.

The emp table stores the employee information:

CREATE TABLE emp
(  empno    NUMBER PRIMARY KEY,
   empname  VARCHAR2(20),
   salary   NUMBER,
   deptno   NUMBER );

The emp_t type contains a reference to the department. We need a dummy department type so that the emp_t type creation succeeds.

CREATE TYPE dept_t;
/

The employee type includes a reference to the department:

CREATE TYPE emp_t AS OBJECT
( eno NUMBER,
  ename VARCHAR2(20),
  salary  NUMBER,
  deptref REF dept_t );
/

We represent the list of references to employees as a nested table:

CREATE TYPE employee_list_ref_t AS TABLE OF REF emp_t;
/

The department table is a typical relational table:

CREATE TABLE dept
(   deptno        NUMBER PRIMARY KEY,
    deptname      VARCHAR2(20),
    deptstreet    VARCHAR2(20),
    deptcity      VARCHAR2(10),
    deptstate     CHAR(2),
    deptzip       VARCHAR2(10) );

To create object views, we need object types that map to columns from the relational tables:

CREATE TYPE address_t AS OBJECT 
( street        VARCHAR2(20),
   city         VARCHAR2(10),
   state        CHAR(2),
   zip          VARCHAR2(10));
/

We earlier created an incomplete type; now we fill in its definition:

CREATE OR REPLACE TYPE dept_t AS OBJECT
( dno           NUMBER,
  dname         VARCHAR2(20),
  deptaddr      address_t,
  empreflist    employee_list_ref_t);
/

Creating Object Views with Circular References

Now that we have the underlying relational table definitions, we create the object views on top of them.

Method 1: Re-create First View After Creating Second View

We first create the employee view with a null in the deptref column. Later, we will turn that column into a reference.

CREATE VIEW emp_view OF emp_t WITH OBJECT IDENTIFIER(eno)
   AS SELECT e.empno, e.empname, e.salary, NULL
         FROM emp e;

Next, we create the department view, which includes references to the employee objects.

CREATE VIEW dept_view OF dept_t WITH OBJECT IDENTIFIER(dno) 
   AS SELECT d.deptno, d.deptname, 
                address_t(d.deptstreet,d.deptcity,d.deptstate,d.deptzip),
                CAST( MULTISET (
                           SELECT MAKE_REF(emp_view, e.empno)
                           FROM emp e 
                           WHERE e.deptno = d.deptno) 
                        AS employee_list_ref_t)
   FROM dept d; 

We create a list of references to employee objects, instead of including the entire employee object. We now re-create the employee view with the reference to the department view.

CREATE OR REPLACE VIEW emp_view OF emp_t WITH OBJECT IDENTIFIER(eno)
   AS SELECT e.empno, e.empname, e.salary, 
                       MAKE_REF(dept_view, e.deptno)
         FROM emp e;

This creates the views.

Method 2: Create First View Using FORCE Keyword

If we are sure that the view creation statement has no syntax errors, we can use the FORCE keyword to force the creation of the first view without the other view being present.

First, we create an employee view that includes a reference to the department view, which does not exist at this point. This view cannot be queried until the department view is created properly.

CREATE OR REPLACE FORCE VIEW emp_view OF emp_t WITH OBJECT IDENTIFIER(eno)
   AS SELECT e.empno, e.empname, e.salary, 
                       MAKE_REF(dept_view, e.deptno)
         FROM emp e;

Next, we create a department view that includes references to the employee objects. We do not have to use the FORCE keyword here, because emp_view already exists.

CREATE OR REPLACE VIEW dept_view OF dept_t WITH OBJECT IDENTIFIER(dno) 
   AS SELECT d.deptno, d.deptname, 
                address_t(d.deptstreet,d.deptcity,d.deptstate,d.deptzip),
                CAST( MULTISET (
                           SELECT MAKE_REF(emp_view, e.empno)
                           FROM emp e 
                           WHERE e.deptno = d.deptno) 
                        AS employee_list_ref_t)
   FROM   dept d; 

This allows us to query the department view, getting the employee object by de-referencing the employee reference from the nested table empreflist:

SELECT DEREF(e.COLUMN_VALUE)
  FROM TABLE( SELECT e.empreflist FROM dept_view e WHERE e.dno = 100) e;

COLUMN_VALUE is a special name that represents the scalar value in a scalar nested table. In this case, COLUMN_VALUE denotes the reference to the employee objects in the nested table empreflist.

We can also access only the employee number of all those employees whose name begins with John.

SELECT e.COLUMN_VALUE.eno
  FROM TABLE(SELECT e.empreflist FROM dept_view e WHERE e.dno = 100) e
 WHERE e.COLUMN_VALUE.ename like 'John%';

To get a tabular output, unnest the list of references by joining the department table with the items in its nested table:

SELECT d.dno, e.COLUMN_VALUE.eno, e.COLUMN_VALUE.ename
  FROM dept_view d, TABLE(d.empreflist) e
 WHERE e.COLUMN_VALUE.ename like 'John%' 
  AND d.dno = 100;

Finally, we can rewrite the preceding query to use the emp_view instead of the dept_view to show how you can navigate from one view to the other:

SELECT e.deptref.dno, DEREF(f.COLUMN_VALUE)
  FROM emp_view e, TABLE(e.deptref.empreflist) f
 WHERE e.deptref.dno = 100 
  AND f.COLUMN_VALUE.ename like 'John%';

Object View Hierarchies

An object view hierarchy is a set of object views each of which is based on a different type in a type hierarchy. Subviews in a view hierarchy are created under a superview, analogously to the way subtypes in a type hierarchy are created under a supertype.

Each object view in a view hierarchy is populated with objects of a single type, but queries on a given view implicitly address its subviews as well. Thus an object view hierarchy gives you a simple way to frame queries that can return a polymorphic set of objects of a given level of specialization or greater.

For example, suppose you have the following type hierarchy, with person_typ as the root:

Figure 5-1 Object View Hierarchy

Description of adobj028.gif follows


If you have created an object view hierarchy based on this type hierarchy, with an object view built on each type, you can query the object view that corresponds to the level of specialization you are interested in. For instance, you can query the view of student_typ to get a result set that contains only students, including part-time students.

You can base the root view of an object view hierarchy on any type in a type hierarchy: you do not need to start the object view hierarchy at the root type. Nor do you need to extend an object view hierarchy to every leaf of a type hierarchy or cover every branch. However, you cannot skip intervening subtypes in the line of descent. Any subview must be based on a direct subtype of the type of its direct superview.

Just as a type can have multiple sibling subtypes, an object view can have multiple sibling subviews. But a subview based on a given type can participate in only one object view hierarchy: two different object view hierarchies cannot each have a subview based on the same subtype.

A subview inherits the object identifier (OID) from its superview. An OID cannot be explicitly specified in any subview.

A root view can explicitly specify an object identifier using the WITH OBJECT ID clause. If the OID is system-generated or the clause is not specified in the root view, then subviews can be created only if the root view is based on a table or view that also uses a system generated OID.

The query underlying a view determines whether the view is updatable. For a view to be updatable, its query must contain no joins, set operators, aggregate functions, GROUP BY, DISTINCT, pseudocolumns, or expressions. The same applies to subviews.

If a view is not updatable, you can define INSTEAD OF triggers to perform appropriate DML actions. Note that INSTEAD OF triggers are not inherited by subviews.

All views in a view hierarchy must be in the same schema.


Note:

You can create views of types that are non-instantiable. A non-instantiable type cannot have instances, so ordinarily there would be no point in creating an object view of such a type. However, a non-instantiable type can have subtypes that are instantiable. The ability to create object views of non-instantiable types enables you to base an object view hierarchy on a type hierarchy that contains a non-instantiable type.

Creating an Object View Hierarchy

You build an object view hierarchy by creating subviews under a root view. You do this by using the UNDER keyword in the CREATE VIEW statement, as show in Example 5-9.

The same object view hierarchy can be based on different underlying storage models. In other words, a variety of layouts or designs of underlying tables can produce the same object view hierarchy. The design of the underlying storage model has implications for the performance and updatability of the object view hierarchy.

The following examples show three possible storage models. In the first, a flat model, all views in the object view hierarchy are based on the same table. In the second, a horizontal model, each view has a one-to-one correspondence with a different table. And in the third, a vertical model, the views are constructed using joins.

The Flat Model

In the flat model, all the views in the hierarchy are based on the same table. In the following example, the single table AllPersons contains columns for all the attributes of person_typ, student_typ, or employee_typ.

Figure 5-2 Flat Storage Model for Object View Hierarchy

Description of adobj030.gif follows


CREATE TABLE AllPersons
( typeid NUMBER(1), 
  ssn NUMBER, 
  name VARCHAR2(30), 
  address VARCHAR2(100),
  deptid NUMBER,
  major VARCHAR2(30),
  empid NUMBER, 
  mgr VARCHAR2(30));
  

The typeid column identifies the type of each row. Possible values are:

-- 1 = person_typ
-- 2 = student_typ
-- 3 = employee_typ

CREATE TYPE person_typ AS OBJECT
( ssn NUMBER,
  name VARCHAR2(30),
  address VARCHAR2(100)) NOT FINAL;/

CREATE TYPE student_typ UNDER person_typ 
( deptid NUMBER,
   major VARCHAR2(30)) NOT FINAL;/

CREATE TYPE employee_typ UNDER person_typ
( empid NUMBER, 
  mgr VARCHAR2(30));/

The following statements create the views that make up the object view hierarchy:

Example 5-9 Creating an Object View Hierarchy

CREATE VIEW Person_v OF person_typ
  WITH OBJECT OID(ssn) AS
  SELECT ssn, name, address 
  FROM AllPersons 
  WHERE typeid = 1;

CREATE VIEW Student_v OF student_typ UNDER Person_v
  AS 
  SELECT ssn, name, address, deptid, major
  FROM AllPersons
  WHERE typeid = 2;

CREATE VIEW Employee_v OF employee_typ UNDER Person_v
  AS
  SELECT ssn, name, address, empid, mgr
  FROM AllPersons
  WHERE typeid = 3;

The flat model has the advantage of simplicity and poses no obstacles to supporting indexes and constraints. Its drawbacks are:

  • A single table cannot contain more than 1000 columns, so the flat model imposes a 1000-column limit on the total number of columns that the object view hierarchy can contain.

  • Each row of the table will have NULLs for all the attributes not belonging to its type. Such non-trailing NULLs can adversely affect performance.

The Horizontal Model

On the horizontal model, each view or subview is based on a different table. In the example, the tables are relational, but they could just as well be object tables for which column substitutability is turned off.

Figure 5-3 Horizontal Storage Model for Object View Hierarchy

Description of adobj031.gif follows


CREATE TABLE only_persons
( ssn NUMBER,
  name VARCHAR2(30),
  address VARCHAR2(100));

CREATE TABLE only_students
( ssn NUMBER, 
  name VARCHAR2(30),
  address VARCHAR2(100), 
  deptid NUMBER,  
  major VARCHAR2(30));

CREATE TABLE only_employees
( ssn NUMBER, 
  name VARCHAR2(30),
  address VARCHAR2(100), 
  empid NUMBER, 
  mgr VARCHAR2(30));

These are the views:

CREATE OR REPLACE VIEW Person_v OF person_typ
  WITH OBJECT OID(ssn) AS
  SELECT * 
  FROM only_persons 

CREATE OR REPLACE VIEW Student_v OF student_typ UNDER Person_v
  AS 
  SELECT *
  FROM only_students;

CREATE OR REPlACE VIEW Employee_v OF employee_typ UNDER Person_v
  AS
  SELECT * 
  FROM only_employees;

The horizontal model is very efficient at processing queries of the form:

SELECT VALUE(p) FROM Person_v p
  WHERE VALUE(p) IS OF (ONLY student_typ);

Such queries need access only a single physical table to get all the objects of the specific type. The drawbacks of this model are that queries of the sort SELECT * FROM view require performing a UNION over all the underlying tables and projecting the rows over just the columns in the specified view. (See "Querying a View in a Hierarchy".) Also, indexes on attributes (and unique constraints) must span multiple tables, and support for this does not currently exist.

The Vertical Model

In the vertical model, there is a physical table corresponding to each view in the hierarchy, but each physical table stores only those attributes that are unique to its corresponding subtype.

Figure 5-4 Vertical Storage Model for Object View Hierarchy

Description of adobj032.gif follows


CREATE TABLE all_personattrs 
( typeid NUMBER,
  ssn NUMBER,  
  name VARCHAR2(30),
  address VARCHAR2(100));

CREATE TABLE all_studentattrs
( ssn NUMBER, 
  deptid NUMBER, 
  major VARCHAR2(30));

CREATE TABLE all_employeeattrs
( ssn NUMBER,
  empid NUMBER, 
  mgr VARCHAR2(30));

CREATE OR REPLACE VIEW Person_v OF person_typ 
WITH OBJECT OID(ssn) AS
  SELECT ssn, name, address 
  FROM all_personattrs 
  WHERE typeid = 1;

CREATE OR REPLACE VIEW Student_v OF student_typ UNDER Person_v
  AS 
  SELECT x.ssn, x.name, x.address, y.deptid, y.major
  FROM all_personattrs x, all_studentattrs y
  WHERE x.typeid = 2 AND x.ssn = y.ssn;

CREATE OR REPLACE VIEW Employee_v OF employee_typ UNDER Person_v
  AS
  SELECT x.ssn, x.name, x.address, y.empid, y.mgr
  FROM all_personattrs x, all_employeeattrs y
  WHERE x.typeid = 3 AND x.ssn = y.ssn;

The vertical model can efficiently process queries of the kind SELECT * FROM root_view, and it is possible to index individual attributes and impose unique constraints on them. However, to re-create an instance of a type, a join over OIDs must be performed for each level that the type is removed from the root in the hierarchy.

Querying a View in a Hierarchy

You can query any view or subview in an object view hierarchy; rows are returned for the declared type of the view that you query and for any of that type's subtypes. So, for instance, in an object view hierarchy based on the person_typ type hierarchy, you can query the view of person_typ to get a result set that contains all persons, including students and employees; or you can query the view of student_typ to get a result set that contains only students, including part-time students.

In the SELECT list of a query, you can include either functions such as REF() and VALUE() that return an object instance, or you can specify object attributes of the view's declared type, such as the name and ssn attributes of person_typ.

If you specify functions, to return object instances, the query returns a polymorphic result set: that is, it returns instances of both the view's declared type and any subtypes of that type.

For example, the following query returns instances of persons, employees, and students of all types, as well as REFs to those instances.

SELECT REF(p), VALUE(p) FROM Person_v p;

If you specify individual attributes of the view's declared type in the SELECT list or do a SELECT *, again the query returns rows for the view's declared type and any subtypes of that type, but these rows are projected over columns for the attributes of the view's declared type, and only those columns are used. In other words, the subtypes are represented only with respect to the attributes they inherit from and share with the view's declared type.

So, for example, the following query returns rows for all persons and rows for employees and students of all types, but the result uses only the columns for the attributes of person_typ—namely, name, ssn, and address. It does not show rows for attributes added in the subtypes, such as the deptid attribute of student_typ.

SELECT * FROM Person_v;

To exclude subviews from the result, use the ONLY keyword. The ONLY keyword confines the selection to the declared type of the view that you are querying:

SELECT VALUE(p) FROM ONLY(Person_v) p;

Privileges for Operations on View Hierarchies

Generally, a query on a view with subviews requires only the SELECT privilege on the view being referenced and does not require any explicit privileges on subviews. For example, the following query requires only SELECT privileges on Person_v but not on any of its subviews.

SELECT * FROM Person_v;

However, a query that selects for any attributes added in subtypes but not used by the root type requires the SELECT privilege on all subviews as well. Such subtype attributes may hold sensitive information that should reasonably require additional privileges to access.

The following query, for example, requires SELECT privileges on Person_v and also on Student_v, Employee_v (and on any other subview of Person_v) because the query selects object instances and thus gets all the attributes of the subtypes.

SELECT VALUE(p) FROM Person_v p;

To simplify the process of granting SELECT privileges on an entire view hierarchy, you can use the HIERARCHY option. Specifying the HIERARCHY option when granting a user SELECT privileges on a view implicitly grants SELECT privileges on all current and future subviews of the view as well. For example:

GRANT SELECT ON Person_v TO oe WITH HIERARCHY OPTION;

A query that excludes rows belonging to subviews also requires SELECT privileges on all subviews. The reason is that information about which rows belong exclusively to the most specific type of an instance may be sensitive, so the system requires SELECT privileges on subviews for queries (such as the following one) that exclude all rows from subviews.

SELECT * FROM OrNLY(Person_v);

PKWPKpUI OEBPS/toc.ncx( Oracle® Database Application Developer's Guide - Object-Relational Features, 10g Release 2 (10.2) Cover Title and Copyright Information Contents Send Us Your Comments Preface What's New in Object-Relational Features? 1 Introduction to Oracle Objects 2 Basic Components of Oracle Objects 3 Support for Collection Datatypes 4 Object Support in Oracle Programming Environments 5 Applying an Object Model to Relational Data 6 Managing Oracle Objects 7 Advanced Topics for Oracle Objects 8 Design Considerations for Oracle Objects A Sample Application Using Object-Relational Features Index Copyright PK- ( PKpUIOEBPS/adobj036.gif$`GIF89a;ZWW񬫫LIIuss0-->;;geeZWXLIJ?;\ afO )=*m|T_d Ңp2ٹ\`k i$.K9VF?޺ T$;Zi`@"3F(|ICp DGʢ Z2Ws',, /Q.$[IB#CtսPu0Wo^uرMv-c͊jÒvۧ -MvvS3w2{߂xK6ὑG.m&w砇.褗Nzꬷnrx0!wL܎{$:H N/|.ʧCxn׽N0O=!}8oH|NA>-w~|KܼB6Oc?atr`"_B>!Zْ`E&B2QPEBA&4= c!,( NJCD ੈ9 D2BO3lW g xAJ e:PD0l12|B咢"vNH*0b4*6dlBދU s0^Bde6mL%^#RCo< ^192F.!|U PrF*3c,h"_)Mh*JL|5zHNH@#%x>s 0Q2H6@CHц )RQCK?L IC؃"VTJ'G0J2*!8db8s:F>ë@ `2Hg"T -蘂|(]5, cC=9%ΤJd̋7 ePnx#\Bf`$*NO(s;`R|'cTY4̣RJ@Z5ueئ,;% RæBZh6-8J Ӣk׺"ܘ-3jk[pV"moMU6sp"#IJd87JJ*#DG@7߸[) Kw]ᖍcgq#-["uΤ&<0_|M-a텸H (׼~WeF%8 qd-أ>eT?`O <Jf0 `<\9,8GRB|W߸[-Wj"0ĻJ9gbQʜڍwˀrm?gJG]Aj횢}pd}R4ڌ9d?ÕEy&ήl̶v0mrst*2"(_,!d"@5TRv6HDm[\TO:N 9A?isĴ_[S3F-¼\n7(u9D, 8w$Dd+-I~_.Tc]OG&@/_qBO-OXY\ORrJdXzoV --UPWM;*G;DF #! U30 J89L&,xrKR# JgSd}_Rd;Qc'{BqvG(@8<z v2 2g> |- ٗ"X1|3Ky['sĽ.\;'?@!, %l4h q_})4J`̩k}>!g}-wV$}{8+#pIy~^+oR![HqFfSdaBhqB{&8*H.Ab,7'`~iwxqO0nh$w!0dx'Qt dF{V88P߀kjh'/UeKeS]ulU"6cG ` m%Ї:ganRsT a󠆎zٗc}~@ 9gM9 #qYx' C.0Hcط& J ɘ hG 5huoňwc-ph;+PiW:4~&Cu0LSJ3܈9p8c @qWYk4aD1 UnPETibj#'Flgc[6CǨ 9allR`C!dD!}I BtQXG'eS0a#f3JeS4yfYeCXidTt3yFFb'$qRnѕ!` p c|\/`1-00/W4ȏٍɉ%V0 di y 6y Mi@_w ʼn ?k7ɗ0zUR6Xii y?tPFqW!}Y) yӡWiXppF #~'EH`!%vyP rh)Z,vzj-*ē4M9gy~(`ZAY8\ɚ`}C@=Z HmJؤ&8Rjȥ]_Z`jSp =kʦ) `=IPo2L| YHq*h)a치Q QnuY*96,sᘬ-S(v!%%߁#J&f(5~Odg*1~C9zz[~#/"M"U#ZǺ!Z@F'-ŸZi2tkII檪 V:8Qz﵍zjoZzJ+ۚʯ ʰESlz0" ;˱1ZJcf+2;4{8;lBJ>@B;DK֪EL۴NA{ T[V{D+ \۵^`b;d[f{hjl۶npr;t[v{xz|۷~;[{X۸NOฒ;{V9۹p `M{ 0 F3|-k[fa"%K0KZ++{ȫ ۥ՛[ ˻aKHнI@jG%ʾFྗ )/@뼿[ ˿QAwB@Rr?Kr"Xc$ NtE(R!-`Vٖ%ku+>etQ;;G,[${6KR# 4Xrk,+p2#a-֡%‹3ĺj+Uo<\>$ "VXL%!PZv!6PEtg)k@qKfYnNJ Dj2Xh*L:'ĺ%l!c:u((Bcg!upWUyx% BbDi6V1<-0dLlk:L\ ]^.mqm+6OA4BxYqMLX; &l`8qrq-pR' G@lC1 dk54i\4$&ĒAqNܖJ<\-"F+_?BV6Exu)Ccd4fwOh&E.e .`)ćX-n|[UtwIu0hi?C.`&TjF-*! FDY.^R*qBY&&v+lY 6|ς!h<" P iP L LOJc!@&4*$35`吜nbG6 a 2@j&#h|fao $r2:»&ԏ`K6W|{*G}&xl.&'#>p:+)؞u{ f3 SYlAUvpJI_ˌ f:WŃoc 1봃; Kr=#D0\)5/͹;vߍ޷..71D:]%m(ω3<~y 2@KP HO2Е'9# ޠ^{F`5~X!2 5Ȥ%"1Pj%8+p'2^P5rwI)>l@:0Ikp*0X! ?)0; b }$ ~CLI&# L@w%E"~乕<; "V$b|c( 8DB]2`\g!,e*DxF1ȗF!z⚁Cx8^#:'"H0 =K"ً1bxl Í6 !Z"< <\tr)zR>䉃rD$ C"=)J#֎I1Dz-K-Ȓ%a0-ʥ'!i:i3=Dm2 >2RH‚@ %nŠ֌ W T"ႎ",?KёUR:Z ZfR%0 V:< d/|JIި$J +EzQmN0T`F3TʚJ-X E@_+mP T"%82.I( d>8,^da25rlG@2x50-Hֽ¹m2؁LK*GiQ>Ǻ^q3p܁os9D ^06Q $cCa*j2AXyaMeqYƦIj||FITSS ڡZEim +Xۦ""&`Gfi.@ IB~ s`N>kD`a/ģ5f'l0hI5\<(<ѫD J{H !kDH](ġ-G|^恄KD(7$aXG >kh2 8trTe''@wGL eK$pQvJ4Zߦ>{x#*qhbOG$bx8'Op!K$O8Tݶ)xZl4Թ5 B=\ J!䂈a jԢ"u@hL͢B~ =`Kd^, @AZ"#ӱIALW9Tو%)TUE=@'^ $E!h &R,o BD0 \Lɣ>%EYW4le!YaL[#/L&iZƽ%4%C; ,a$]NhB="d ^B4DDHL Be534f }:,/C4JaTETeXy#\r;zBD%I![ɁdS.  PB #SHg fV I߀R[xB%P1!GbPI h FrPgL]ܜgem&%n*GB(5=h]juDeuu]ƇR(nV(mh(o\h莢ƌhZhb ")gƈ:ic4iR ]RƔzhXif(Fwؚiiii6j  $HT@ 0j:BjJRjZbjjBµLꨒjꩢ꣚@jjRjꪥ;PKImK$$PKpUIOEBPS/adobj031.gif!qGIF89a???@@@999///ooo𠠠 ___pppPPPOOO000```rrrUUU:::>>><<<!.,] 8p# @B!ÇR!ŋ3jȱǏ Cr)z$8ɗ0cʜI 8qxhÞ"0`ѣH"zBEXjݺq &#0B **8uvġi؊mVX.*MAB#K؁B&Pb.8 d}ɸs|WU!@T}¸@4}!NV!@0> 77vo{/sp ,B =BaoDqcUehqQ1ބ^ě xPY-a֓P]^~ @C_ AuAX P4TDI TvLEP8UYe,po!te. ytE^Tg^S !)@D}(U*eooSTOفoUw;g2)UfxVgf!͑UQs OʂKA~HC0"Fv!&Xc=Y}Q9eDDU) pP! S4dqyTnTs`n7Th&uy=Y>q 'qޔ,QpRUD"+2zƹqeTZB6q{ED͍֡VH'fnӴhѺPWmX/\w`-dm ggp wjOMx|߀.G-'7n8F,Wngw砇.@sy訧ꬷN9>>no.  .ć{[|7߼0BZԫ|:w⧯~O=ǿ>~ϋ^gގ~HA)zE'% !.<)((@E51'La\B@$@cA @I`Bp i !I\b)'DqU !e'1j@Ђ\@ Z|`1@`X`Fx H x`q#(1 J ^$t.Q # |# IHC"R$#iĤ&I[ %5 (@ H -0<)(x@0D4@4ЀHӑ݉cN.r>@)Q\A̦po2`9ѩN wAb| "#:PBI!!.hzR a%b' aO(L'"hOZ(/!').{x#p(0O#. @qϢ"H|U1+w!2'9%.('SkQQ2RC1W{aa}8Q I؄!,z&6  t1*j61q *3Sh'6iw Q1*T~V]Sr }/.c1I=9"uCՙ7&9I%7q)9Yyٛ)M9ęʹ9՜ &o΃_i9Y@`ީѝ䉞Y;YҞ;IY;ɞjnHɟ J牟ꉠ>) Cjo:*A& Sy0qs]Y]R/Tj:*eJ JBz9-9T 0ʥ]p$WMD`549t^sBCsBXIgj9~:ZA2hZsBPH:9zT.\WeJ:m49"0^ MZ#j9OJ.E9ڪZ*$94F*:(~S]欛5F ddD  `fGEvP^uX\*UDDŽh] ЮwƮzfJVx$oHEE\z [DtD\QUU7Pd2Ff9Cr3=FiгԱ:DZZZ\kD\DkLYuԮ$i-J9GB CEo[f.ձ0OkETN)[T.B;^S4N `PP$EIuc~Tu]MtFIOjePBH[oV:N,_K[UfavMM5T섴D[YTPM*Zff{Bd^R$*9VTfgG[D]9tJ^㹞GMIPTkNĮ촨tXS_DGEuF%/\ش$9{f<+FXTdW[EqıQƹ#N)Tt:)e[ @OS†8fz9ELG"$&~ct=)>@D+.UJL9T^V>8mv\^ tZ7d^f~hVjnpj~b.v~xpz~瀮t9^~舞芾>^~阞难>^~ꨞꪾ>wC:!!37n b%]=C6[˗xΎ~!S 3 (~c%6e Kݞzh&8Q 7#%H;4HWRЄY{78"AQ@(%t(:肦ƒ!1 Ƀ( E2zXх_a`q_1/2HR&`(=12B *BXAB.zh",MB[ Ʊ0wa*Ē&!.,+wQ죨'ZRr20C!)@qX(QM_ {ψ8B%Oa*(To"Јw+p"ha&"I&4~# (x"AXYye@? i$OX?!aX*3ya , np0A!\0@]t`Q ƄV"dH  .:LB jSN=}TPET9EEjhKB(qNJ T Z5Jtj\uq&Laos-RBl\VXavpie]L Z.9lڵmغ{r/S 1f{aP~[vݵWPZ)Pwݿ@>~kg+?D={̴/B /0C 7C?1DG&$1EWdE_\Q).Fo1GwG2H!Ġ!D2I%kdAf\2J)r X2K-}l!Z3L1$L3D3M5dM7 M9N0K;O??%4.,4QE]NF KH/t@3MI@SQGMQROJQeM[=PaRSkT'-ŵWE_SYy >o5Q]5YgD6ek6[oŌ[>\05m6juWNr]z\w.zj^cWy`T@8L @a3P\{ZbB)V;FO'# ˩ۂ :8=n!Ϥ\"LIU X`̧V@`a"f∯nP 3d/&/hj5f61EN {`o^ &S%. Ʉ>7i>n鮿^a WY6n[n=Nߛts3ܢ/Hp N 0ځP%nA@>|& 8I/ 0Ђ9`o+ژfł8  0)@_( `[ O4@3D"Q84y@ׂn|Y7CH CR iT&qj`u3b|1dQr-Nx>pui, 2rH>UZ G4`F@Z0k\$ L2x>0A9jf!&w&l]c笋1$N]@08=H+4`a$B0J1ֆ\2_z07,)rw- #IR2t4JO kM44e&od5 |Y7%:Ɉo@i?o6cDZfS a (rֽIIp+3ľI{ (FH>VtaΒƅi@U$&($8`gIlj*WzՒ,:YDe6mXuDK`?UΘXAՕS`T@lh,{'Aj,V[?ԗ4H I’1OVh h$&[rdGXV*zXlhIkVpKUU'9R~k\<ahrWZ}_jZG e$ Uo~_ \e-ւ6fnՐb }Ptm7\rp|j2W:},ea N&q  J. T H>, @G;e.cARd1 ,U&oy s&=tj꘭13k\[Q#7H:֍>=#I&)oJ\75Um[4ș-yZR,gg?^87G5-o˳sAmi^Zэr|g躘 eV䵙'htTk7ۦrL{ܦ.]7m 7{a I^"4\^(0si9TDWaES} .Wç&T֍Eu?Weo/m'{Yuu6lގTtmwje{;x ]WGSGiCx_^|yk~6=>_uYhK}T$מJv߼m{WJ>G~Gd_χ~ߢ̉ ~}w?~GO??!֯$ ;PK$*!!PKpUIOEBPS/adobj029.gifBGIF89a?ddd~~~333̀jjj[[[SSSqqqJJJ,,,>>>煅@@@zzz򢢢###vvvmmmEEE999!?,pH,Ȥrl:ШtJZجvzxL.zn|Nۇk,)*W8)T)-D'8wr>>,B)>*>N$W/>T+>.32D7F D?>' ? ?B #>9  7 8 BD?F,(`A?4B{*c l#B ?pÅxƲ˗a.‡j("kr>ZE >Re!J3~OCQ !3p|@A4^~ba,` LƲPڪvA))L94! fx@rE஡"thA)}[v Q,6 p ("Xwk߾MNZ%(8gF!#GruGOyEZ^զ 3tF@ DpQ0S C|!(݉(>~( )DM L4U}̵%|@ˀ"63@*;!\C DP2| F(;+(tr1(51g@T?d:||6 `Skeg*$5:?(/FSR[' uA!v¼ MuM8"5Yx,3(PC<:Wa(,,p',!p&  U,\ -IY |6rޛC~`'%]0&Q;.UBS?H ksR P,"@ JaЂ?0<$X @ x @ D4M8 ;8ߔW>u4[?E Yy$b? @[&HvJ"2\pB,; p TAG/\<>Zv# s) ?\id}#@R_5nG6oۆTQ0@w "p& x 0G q>lR`y! n %?D  HH"!lc+6p~T_a T@ 01A` 61 #6p#=x̣$PZbABT\ A"$"II0:2D$+^2Dtd(C)($eTL.GZFܥ0+K_>2VLcˌ&ۚBBS5kfRۦ`Ўw@08 MJAbPx@d0μC ]C 8s@56 :a_0"@e'HIE%Ix TEBC+V|0@ BV5H Ԫ)xjT9JtXd*׶* |`& | o(A M i+B 5^ (jh?U>,+P:+:f)`&(k*XؾҔ 795#@A΄ ({SE:@ 0dwdHJUdx[gl8 (P l@P"QĠ v' s~0+9|]l?ho6V ֙X2{NO8%T`_@J6';8lUn +p΂YPpV>֛g*ٗu7gψŸkh4:ѐ~¢W3<:ҘV¤YYX7\:Ӡ.¦AYi3|:Ԩ-;݆SԪnHWc:jmkHZTkDc ? TЁtЎMhh >\rN=5z ȃAI~Vû;qR*ĞZD5.'N[2G§FcT@1pM\*ҁ:KL@d|ݸ '<@e\ -D=;\7=b-+ 老`tͨ^QP!83N rFE\  s; x7| x`P! ᓕ_Ww5U||ځh"4cAL2L/>𢘁fv?gD0>1DO6{.n3>H-%įCr`G'"pS`p?~XIWǂ~} H hw8qTȁndg$Xge`4D5 9Hop#@ P~9W`5x8A[# ss&tRXQPS \SH wPX:P*,_h#P~@X%qh,8e P6t0A8 vH6@%8@YVu(  @oCCOr `zH88{0%c`L 47pw*w ` u6_6 y>1"y9 |$ X  $8&EJ87ipOt@i2)XrW U eE)[6 #v /8X` 65a+@r E8 o I8ُ^hhW\C0 &re9di/)9Yf)ʟf` 7|mࠜ6  j)Hl ;":h&z'"2:4Z6J @I* y. `r>fH=*1EHGZ ʤOZH,t0wPV X(^j`0d:. &`Iʢnz"p,0u:kZmdڧtjjJ1*rt0jn`sJZ -:@(YcZJKʪp yE4=,I*fp 5'9Eu=uIzΪ :0 %` Iߺ+:X|"!/0vHڞVpG 0ePS꧞Z{jY⫇>=2&Z,k 8pD{8puUK"8A;K=ۨS[Z.Ӻ!p0({[[peZʚZp rGĶlqЬ?χv+L ˲kL[|{~{M0`Pt鶶*[K롫{J^Իg‹J۠KۼF\4I;Tѵc'X_z/[苬k>ZYG[0%<{kK&%<૲\D^po$L\X{g %v?]0&}+6,8 ʫmBP Tq5l5"n^`d'-2e4fʒ !5Xh<_nV LQ~F6 Fa K@5,LcPwo 0,Pu0<%eBp%fE0cw  x48 P:p3:>'`NA P'-bXEGUDo-@hf"J̾ln 2sPv;"?A'2f̣q;Q2 6A!p *S1 p- +`C.C$`sdpʄd} ; `0 ɲ(0-0ZĀ +,@=nάǵ kL!ɡ * 1=b5L*%v; 0"B= 7- +75Ո%)Ba/Pv;/u Q r^! ٢  0,M .3- ": ԛ}"[I;" T  2Tdq+T)mĝ-ƍ 2;խʗ}"6B{Qv$ŜԀu7 ,.; :%Z" H!Cf LL / 30Qqw]5$1$m[ nάKB-e").znj K7@4St2aPg0L8~tGeSiM "@4N˳3Ya v+ t_peb@ %D/0PSF1>,3|p^7@O(xP(΢RLT,a-D]`֫t :2PP.2?0+FqWWQAP g!ɋ\ Mksy$ !#w11D/ /LYAd[ yr5 0Qǟpp# 5 "&($ߐX4It>Qզl`a1<фo7cݓǒ|f~"~X"V@x>~:|>NR""Z$|8J"6BXtXPSUWXӸ`kla|tW~ |8J#@*}" ~ 0~\ΟdQqx}h^ A .L1ā\p@S Q * 8PNevZfsJF4qԹ ˝/y>tMG&}S'Pd{JTWNai֡Wf;,:+vq'հe=gWmoK4^To_Ç`GJqKS'o9;GNvA̾ s| %PėFDK0P0Dq:vZZC\(b!*"(*,!0$("['`+Ti ?0 ̘X̐L@@AY ̘@6eFs4@ ǔ~:cf@*D@*(< H( LD@ PA$U(A@pr)ϘD 4Рh"ԑf9]`e>@@N&a ~P i@Rȕ]_[ >'` X@q} 5s(#5mTk0l&*F=V $l)tbPhJ6yx~ c=|ڢP';wag,Q6ݙTTtIi¢gJjnEM >=OI;Qʀ(< ?B0ժV &Ndhu0YњVmU J0BFTG"%9}M " Eǂ} 7Y5 8P  | *`g00m@@ċ%Ql7 5<m~qb7 ,^C03fp+Y˶ل22hc-d8X4;h 5 ЅK>h dЁ0@0 DH`ì!!fv9M=8lx@`= /H< GZ .uNsM< Ȁ* 5`ց2| plX\X؀ ."‰G{ЂtJA 8Y"R,@vP 4nCzZ0:9Q7 2R;h |NR/0 }v1T= zP"iOg }m>x6RȀwяܘ$bApHw`|l %r`؆t*@<`N@A $j`8v,3`` @ \r`@v 8 T`VF@($`RR .TL 0z.W! ︫{ ކ0 B*0G6- 0̲8!~*qȊ%p4p Sl€IG3 {+gk B,Ӑ`lq0 &z (!SB1qّ>8//iQ b1H1An+2t`8."%r")"U!q"A2$EخZ-H>!QP~L&m&q2'ur'yRZ5^Q `z2)r)qrYa"\rh)*q'-(qc( +,)Mv㦒2,2)R8ҥڲ.{r,aGo`$- &0s0 0 0`DL,%Q* 1)2-0;or3q).c.C9s'`R&bY4C4(.H4sB5~b6i&l3+ptSxS.|7d #Q.v  ,`;- ;.3C.F`;z. n9Aҳ;R`>iL@>"; E$;?D>u0`?s6gCs(FztVb@s&`B@ \ >BCm"0`sFq4v(\4i;mC%(]zp)DDH$ `zt`HSxt;l J۴DoBmVi B3BaI@M`l'Et LaK3t`Q CnBS=N=&8A<(b5SatuēvuSCF`WA.@~U*X~3+JtG$`W<XTUW(cW?[H`W%"X'`WI L Y/5n`^u6|uZ!^s@ W,]5`u`@`WAW2OWGVWIBt[2 *B~([fW@uWa cuUIaXw5`]uU`"j0[ivP@5B Fv$v_wj @blVFWogwunB_nW-p`Ws*B/p 5 p7/x>!j#l::q*SDX<\S "7ss qa8"9M͘Gnvq7wuwwyw{l` TwX\u|wyyy7 `7vf xw{{{7|W& B>W=B7 ۲W|7~{Q szWJqbK &D#' 9뷔t7zҷ@ 'ص;bRr!ӀaAG4G:*>?i`@+5W(‘T)t.@0آj@}@@ N@1r[v|p4bzm؊u† f  Xf ;SCY!"`H8`R0`옊KSA"  Pz@qv@n`N3UX:)9 foRz`h73tQzg׸$_.H` Ό{Y%;:4xf Kqma髛cy{" , ,3yX 6xy9]yٟ9k{aYUhNn9ә#G+{࢕ỵy,KMzh8rà˧9M SzI:%TD 2%zۙwbZgx wט+%ڰ˭S؈ 0;'{n%)R3/Qڱ7UazCK{ &\Yk$Akx@;G:Ҥ]{3!z: 6۶Z`?˺W۪Z!+ǻ-۔@!۽dq :IۿK:_%^vfjMsRUA钗N*`KG^{Qn~^Swz2 |WN߷6@z@ȇ\2,.{;\˻̉+'8;! GعYHsWYܜ{W Fe<  (}"^& 7; >=C}GOfR VݱZ =֛`kgZ+qƽ['Q~]ǒӉ}G5|9ҥ=ί= N3Ckۍqͷ Igח6;<=Μi]H޳С]=/ߝCQk]~ ?{]5~MPkӠE#'C Q~ Ϗ?K$5)^ ]kyuۥX9~a|Gߜ}LS=Q1t_>оۦe^s:=<>: k <EKOިS^{Q[m3\ƹ^*=[5 ܰ!q?ɼ:E'@ q? tq#); N? 6Qlo \v@y`&Cq?QI! ̯h>$|Bҩ(ޱ 1 2}t"46&۸OhD "&**&pȤMRVZ^bfNj\u,|d-&D͉jRdm}9LDDHx Pl ,ݨ\+TDoP0D9Pp{al\O\thE "H\tPq E?0Lab?iYNLr%˖.| 5ԩT oz Z^ *Te.nzz)6]&|PPc?X40:Z 4a>dP /|P@щx"F$MɡE)EPJyNY} yGDC 9P<C@xbvN@#j'eшjf8VF>8|!mݻy `q }@GD`qx3.I$?dc nЄY}Yb!~ d:sj#13V0qf(#pD`%,ttQth!Ũ?vᥗ 1xBt ]B|G 0,$eb"XGEDR`~6%Łj @3D Ɇ@!b 3C)B!8*ʂ .UY@b7 !` 7|%Z :j2@),C8F752j~}TY"^G~7P Ox Pd&l; ;@XM& Q 5Pp E8 ) @LS@A 6 t~5 _p]E? QC @";Dv4@ !K_ |4}4#L !"l)D h8O{ 8A 3<d9l0穃$- ||k>h+ &#`^ '#.lYƨ@[q!2غ #:>!8tW04 + 9F' 0) F6*>8M#ˆ FQA8B )M4zƒR(eTXV 8LЁ֖4 ࠑ,%|@i 0&x4 A Yv2lܝY@@КЄ`!݄`*@@#0|%*&$sh"SA* D0Cp0N+?x$ HAHje(US 8@E3xn"(2 Om F  G6P+,A|ԷΨ\ x QQ! D"U=gYu9RUK ⃨¯(@`",j`0NR ,9TK5 ZQ @ '0c$Zɷ.xTMA`jխ"Lw6 rʖt- XI]yLF TAD1aн}ؠ8p l p>1[)wt}1klcVp+1{ll>23 d J^r$39Rv[)c92/K\ޗl381Q^e~3G5v3?gz͹ςA#ͅס//U~4iVMɍ@ `}d=6ƳpA(Ti]:U^r#l$6F5([0!ENhu9,LX@{.\K5k%0" |{A>2WAg `g 箤Af@>,^f02PPY>0f7@^ Zxy 3]< M`x<;81bYI"@m5r@5iNIY -&00T ^Uaǰ@DSYGuu"_/Ѐ!F`.zì \>o@Qle$ c>k<sɣ75( ,(A3yN #pWHdp'Nx~J pϯ{CF0`vDYsဎ   ߐt Pc'J=?#@"@YT%1 :A3"0vE6RD DHHbIǨd dMLFZFNbNvNdP&OP QA<~<8$1<8HL\ S&@mTd<%mVBXn WUZ:eK9ݓYCiS.1\@%TS*T@`.>@a惡dv(]ڀ[al4HuS ej jf]J:@fxf=Ac%C)k LTH@51Lff<@`JCUh:kZ 8@WSJ>& _f$j*@Wx HoA}2gf '_gw@S6@E'tB@wBgE^ST P8(8 @.rD3\PjT@( `S (\iJ =h팈֘`Ci&  X@2h:h  h8 rV: 1ie)C݆f9j@iJ$ b i6\H@@_nd@$f2EVԨT(8((R"QʙQQ*G0Ra+O,k6ἶB+k, "l*B*, 2+^d"RZ!`lƺz8tN]ɶɢ충,lV˒A,gFb2lllAm!(YB-+mՖHjr-~m׎m^:a+*$Z-Cݾcmݦ-mHL !ʑSQTI*LBj`bewn>$̖8㤀(@.#`W%|.VUU"% nP%0@*B!V @f `\z%:[;%S$ODS$ ':t !T$RS] 4"T@~C-/.hfMg _4 +]@ @"@ ,ޱ%epѐ<@@*@t%EP'X[HP@@pZ@| ڈ@ I u8,x|@b78 D@9@2 4bkHЕ@@G04 FZg3ng1^mlX I) ZNܳpX@+@\8/h@d@|(@ 7y0̀  8}wtb-`|`Xw @m @| :8p@8]<}w t!w Hj p Ԁ ؀, :^S/և.;% 'C@ ^9lx hԊJ^,6Eds @v  @8@O ܞ\=$v@$JPBC@0};C}w@(3}@,{O= < X`@ ^0Kf}KAL@ 4b@-ݷp9H=D(+4U@1~;C~.\Kc;PK„LBBPKpUI OEBPS/toc.htmr7 Table of Contents

Contents

Title and Copyright Information

Send Us Your Comments

Preface

Intended Audience
Documentation Accessibility
Structure
Related Documents
Conventions

What's New in Object-Relational Features?

Oracle Database 10g Release 1 (10.1) New Features in Object-Relational Features

1 Introduction to Oracle Objects

About Oracle Objects
Advantages of Objects
Key Features of the Object-Relational Model
Core Database Key Features
Object Types
Objects
Object Methods
Type Inheritance
Type Evolution
Object Tables
Row Objects and Column Objects
Object Views
References
Collections
Language Binding Features

2 Basic Components of Oracle Objects

SQL Object Types and References
Null Objects and Attributes
Character Length Semantics
Constraints for Object Tables
Indexes for Object Tables
Triggers for Object Tables
Rules for REF Columns and Attributes
Name Resolution
When Table Aliases Are Required
Restriction on Using User-Defined Types with a Remote Database
Object Methods
Member Methods
Methods for Comparing Objects
Map Methods
Order Methods
Guidelines for Comparison Methods
Comparison Methods in Type Hierarchies
Static Methods
Constructor Methods
External Implemented Methods
Inheritance in SQL Object Types
Types and Subtypes
FINAL and NOT FINAL Types and Methods
Creating Subtypes With Overriding Methods
NOT INSTANTIABLE Types and Methods
Inheriting, Overloading, and Overriding Methods
Overloading Methods
Redefining Methods
Restrictions on Overriding Methods
Dynamic Method Dispatch
Substituting Types in a Type Hierarchy
Column and Row Substitutability
Using OBJECT_VALUE and OBJECT_ID with Substitutable Rows
Subtypes Having Supertype Attributes
REF Columns and Attributes
Collection Elements
Creating Subtypes After Creating Substitutable Columns
Dropping Subtypes After Creating Substitutable Columns
Turning Off Substitutability in a New Table
Constraining Substitutability
Modifying Substitutability
Restrictions on Modifying Substitutability
Assignments Across Types
Objects and REFs to Objects
Collection Assignments
Comparisons of Objects, REF Variables, and Collections
Comparing Object Instances
Comparing REF Variables
Functions and Operators Useful with Objects
CAST
CURSOR
DEREF
IS OF type
REF
SYS_TYPEID
TABLE()
TREAT
VALUE

3 Support for Collection Datatypes

Creating Collection Datatypes
Creating an Instance of a VARRAY or Nested Table
Constructor Methods for Collections
Varrays
Nested Tables
Specifying a Tablespace When Storing a Nested Table
Varray Storage
Increasing the Size and Precision of VARRAYs and Nested Tables
Increasing VARRAY Limit Size
Creating a Varray Containing LOB References
Multilevel Collection Types
Nested Table Storage Tables for Multilevel Collection Types
Assignment and Comparison of Multilevel Collections
Constructors for Multilevel Collections
Operations on Collection Datatypes
Querying Collections
Nesting Results of Collection Queries
Unnesting Results of Collection Queries
Unnesting Queries Containing Table Expression Subqueries
Unnesting Queries with Multilevel Collections
Performing DML Operations on Collections
Performing DML on Multilevel Collections
Comparisons of Collections
Equal and Not Equal Comparisons
In Comparisons
Subset of Multiset Comparison
Member of a Nested Table Comparison
Empty Comparison
Set Comparison
Multisets Operations
CARDINALITY
COLLECT
MULTISET EXCEPT
MULTISET INTERSECTION
MULTISET UNION
POWERMULTISET
POWERMULTISET_BY_CARDINALITY
SET

4 Object Support in Oracle Programming Environments

SQL
PL/SQL
Oracle Call Interface (OCI)
Associative Access in OCI Programs
Navigational Access in OCI Programs
Object Cache
Building an OCI Program That Manipulates Objects
Defining User-Defined Constructors in C
Pro*C/C++
Associative Access in Pro*C/C++
Navigational Access in Pro*C/C++
Converting Between Oracle Types and C Types
Oracle Type Translator (OTT)
Oracle C++ Call Interface (OCCI)
OCCI Associative Relational and Object Interfaces
The OCCI Navigational Interface
Oracle Objects For OLE (OO4O)
Representing Objects in Visual Basic (OraObject)
Representing REFs in Visual Basic (OraRef)
Representing VARRAYs and Nested Tables in Visual Basic (OraCollection)
Java: JDBC, Oracle SQLJ, JPublisher, and SQLJ Object Types
JDBC Access to Oracle Object Data
SQLJ Access to Oracle Object Data
Choosing a Data Mapping Strategy
Using JPublisher to Create Java Classes for JDBC and SQLJ Programs
What JPublisher Produces for a User-Defined Object Type
Java Object Storage
Representing SQLJ Types to the Server
Creating SQLJ Object Types
Additional Notes About Mapping
Evolving SQLJ Types
Constraints
Querying SQLJ Objects
Inserting Java Objects
Updating SQLJ Objects
Defining User-Defined Constructors in Java
XML

5 Applying an Object Model to Relational Data

Why Use Object Views
Defining Object Views
Using Object Views in Applications
Nesting Objects in Object Views
Identifying Null Objects in Object Views
Using Nested Tables and Varrays in Object Views
Single-Level Collections in Object Views
Multilevel Collections in Object Views
Specifying Object Identifiers for Object Views
Creating References to View Objects
Modelling Inverse Relationships with Object Views
Updating Object Views
Updating Nested Table Columns in Views
Using INSTEAD OF Triggers to Control Mutating and Validation
Applying the Object Model to Remote Tables
Defining Complex Relationships in Object Views
Tables and Types to Demonstrate Circular View References
Creating Object Views with Circular References
Object View Hierarchies
Creating an Object View Hierarchy
The Flat Model
The Horizontal Model
The Vertical Model
Querying a View in a Hierarchy
Privileges for Operations on View Hierarchies

6 Managing Oracle Objects

Privileges on Object Types and Their Methods
System Privileges for Object Types
Schema Object Privileges
Using Types in New Types or Tables
Example: Privileges on Object Types
Privileges on Type Access and Object Access
Dependencies and Incomplete Types
Completing Incomplete Types
Manually Recompiling a Type
Type Dependencies of Substitutable Tables and Columns
The FORCE Option
Synonyms for Object Types
Creating a Type Synonym
Using a Type Synonym
Describing Schema Objects That Use Synonyms
Dependents of Type Synonyms
Restriction on Replacing a Type Synonym
Dropping Type Synonyms
Renaming Type Synonyms
Public Type Synonyms and Local Schema Objects
Performance Tuning
Tools Providing Support for Objects
Utilities Providing Support for Objects

7 Advanced Topics for Oracle Objects

Storage of Objects
Leaf-Level Attributes
How Row Objects Are Split Across Columns
Hidden Columns for Tables with Column Objects
Hidden Columns for Substitutable Columns and Tables
REFs
Internal Layout of Nested Tables
Internal Layout of VARRAYs
Creating Indexes on Typeids or Attributes
Indexing a Type Discriminant Column
Indexing Subtype Attributes of a Substitutable Column
Type Evolution
Changes Involved When a Type Is Altered
Altering a Type by Adding a Nested Table Attribute
Validating a Type That Has Been Altered
If a Type Change Validation Fails
ALTER TYPE Statement for Type Evolution
ALTER TABLE Statement for Type Evolution
The Attribute-Value Constructor
Constructors and Type Evolution
Advantages of User-Defined Constructors
Defining and Implementing User-Defined Constructors
Overloading and Hiding Constructors
Calling User-Defined Constructors
Constructors for SQLJ Object Types
Transient and Generic Types
User-Defined Aggregate Functions
Partitioning Tables That Contain Oracle Objects
How Locators Improve the Performance of Nested Tables

8 Design Considerations for Oracle Objects

General Storage Considerations for Objects
Storing Objects as Columns or Rows
Column Object Storage
Row Object Storage in Object Tables
Storage Considerations for Object Identifiers (OIDs)
Primary-Key Based OIDs
Performance of Object Comparisons
Design Considerations for REFs
Storage Size of REFs
Integrity Constraints for REF Columns
Performance and Storage Considerations for Scoped REFs
Indexing Scoped REFs
Speeding up Object Access Using the WITH ROWID Option
Design Considerations for Collections
Viewing Object Data in Relational Form with Unnesting Queries
Using Procedures and Functions in Unnesting Queries
Storage Considerations for Varrays
Propagating VARRAY Size Change
Performance of Varrays Versus Nested Tables
Design Considerations for Nested Tables
Nested Table Storage
Nested Table Indexes
Nested Table Locators
Optimizing Set Membership Queries
Design Considerations for Multilevel Collections
Design Considerations for Methods
Choosing a Language for Method Functions
Static Methods
Using SELF IN OUT NOCOPY with Member Procedures
Function-Based Indexes on the Return Values of Type Methods
Writing Reusable Code Using Invoker Rights
Replicating Object Tables and Columns
Replicating Columns of Object, Collection, or REF Type
Replicating Object Tables
Constraints on Objects
Considerations Related to Type Evolution
Pushing a Type Change Out to Clients
Changing Default Constructors
Altering the FINAL Property of a Type
Parallel Queries with Oracle Objects
Design Consideration Tips and Techniques
Deciding Whether to Evolve a Type or Create a Subtype Instead
How ANYDATA Differs from User-Defined Types
Polymorphic Views: An Alternative to an Object View Hierarchy
The SQLJ Object Type
The Intended Use of SQLJ Object Types
Actions Performed When Creating a SQLJ Object Type
Uses of SQLJ Object Types
Uses of Custom Object Types
Differences Between SQLJ and Custom Object Types Through JDBC
Miscellaneous Tips
Column Substitutability and the Number of Attributes in a Hierarchy
Circular Dependencies Among Types

A Sample Application Using Object-Relational Features

Introduction to the Sample Application
Implementing the Schema on the Relational Model
Entities and Relationships
Creating Tables Under the Relational Model
Customer_reltab
PurchaseOrder_reltab
Stock_reltab
LineItems_reltab
Inserting Values Under the Relational Model
Querying Data Under the Relational Model
Updating Data Under the Relational Model
Deleting Data Under the Relational Model
Implementing the Schema on the Object-Relational Model
Defining Types
Method Definitions
The getPONo Method
The sumLineItems Method
The compareCustOrders Method
Creating Object Tables
The Object Table Customer_objtab
Object Datatypes as a Template for Object Tables
Object Identifiers and References
Object Tables with Embedded Objects
The Object Table Stock_objtab
The Object Table PurchaseOrder_objtab
Inserting Values
Querying
Deleting
Evolving Object Types
Adding an Attribute to the Customer Type
Working with Multilevel Collections
Inserting into Nested Tables
Inserting a New Purchase Order with Line Items
Querying Multilevel Nested Tables
Type Inheritance and Substitutable Columns
Creating a Subtype
Inserting Subtypes
Querying Substitutable Columns

Index

PKlrrPKpUIOEBPS/title.htm# Oracle Database Application Developer's Guide - Object-Relational Features 10g Release 2 (10.2)

Oracle® Database

Application Developer's Guide - Object-Relational Features

10g Release 2 (10.2)

B14260-01

June 2005


Oracle Database Application Developer's Guide - Object-Relational Features 10g Release 2 (10.2)

B14260-01

Copyright © 1996, 2005, Oracle. All rights reserved.

Contributors: Geeta Arora, Eric Belden, Chandrasekharan Iyer, Geoff Lee, Anand Manikutty, Valarie Moore, Magdi Morsi, Helen Yeh, Adiel Yoaz, Qin Yu

The Programs (which include both the software and documentation) contain proprietary information; they are provided under a license agreement containing restrictions on use and disclosure and are also protected by copyright, patent, and other intellectual and industrial property laws. Reverse engineering, disassembly, or decompilation of the Programs, except to the extent required to obtain interoperability with other independently created software or as specified by law, is prohibited.

The information contained in this document is subject to change without notice. If you find any problems in the documentation, please report them to us in writing. This document is not warranted to be error-free. Except as may be expressly permitted in your license agreement for these Programs, no part of these Programs may be reproduced or transmitted in any form or by any means, electronic or mechanical, for any purpose.

If the Programs are delivered to the United States Government or anyone licensing or using the Programs on behalf of the United States Government, the following notice is applicable:

U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are "commercial computer software" or "commercial technical data" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, use, duplication, disclosure, modification, and adaptation of the Programs, including documentation and technical data, shall be subject to the licensing restrictions set forth in the applicable Oracle license agreement, and, to the extent applicable, the additional rights set forth in FAR 52.227-19, Commercial Computer Software—Restricted Rights (June 1987). Oracle Corporation, 500 Oracle Parkway, Redwood City, CA 94065

The Programs are not intended for use in any nuclear, aviation, mass transit, medical, or other inherently dangerous applications. It shall be the licensee's responsibility to take all appropriate fail-safe, backup, redundancy and other measures to ensure the safe use of such applications if the Programs are used for such purposes, and we disclaim liability for any damages caused by such use of the Programs.

Oracle, JD Edwards, PeopleSoft, and Retek are registered trademarks of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.

The Programs may provide links to Web sites and access to content, products, and services from third parties. Oracle is not responsible for the availability of, or any content provided on, third-party Web sites. You bear all risks associated with the use of such content. If you choose to purchase any products or services from a third party, the relationship is directly between you and the third party. Oracle is not responsible for: (a) the quality of third-party products or services; or (b) fulfilling any of the terms of the agreement with the third party, including delivery of products or services and warranty obligations related to purchased products or services. Oracle is not responsible for any loss or damage of any sort that you may incur from dealing with any third party.

PKꆒ(#PKpUIOEBPS/adobj020.gifp(GIF89a}T @@@ ///ppp000```___PPPoooOOO???! ,}T@A`H,Ȥrl:ШtJZOvzxL.Bgn𸜝P|vw|lghkʘ_noɕêmٕnu^2MxCO(w]ֱ``F}n JyY0u@&zhnU& ht!|zgfIJ=a5 XŘ)*?4 CS%fM{ҟ3wk{ڦ^=Y"С\Uƪy~@hV^sXXuGNbph\}3b..\f*%gi/t.V :jyՔncZk+fKS!&#KX$')YbX2ixdգ+s$ҴOgNx͆ܙuY;WkKWD4M:,,"u6w@5m@E]o''|#q{f:cuأ錟cl5gNp3-4–M"pMN]X'wyPL _aK&A5uPʣ@{,.JwTg~I[O}(v}?odߓ?\>(p`Rcomxo~<ǿ4$ta ""LD37, G(La c! gHC%`5a e~ !G@Ј^P,P#>*OE7M<3 XE2^ьݻ^P"hĞaq]ȉ/Q]b_7GqX -(J|< QH;NRH TJHҔDR[9F>FV-LLS’#UtYT#IPGS@N2=L&c0;3 d@EҌ&51"Zě ]0{,2fQv줥'W."t+,A p`Ql+_e wҟecSLehcK~]e :fĦ8}AlBDOjJ}3=lKҚ̬gu+{򳗸,ekxȵIl+ Tj%bƔ'=o [´9d/|DƄ4-L  o+?Ծl'ۋN,-廬p0U3t7^ifaT`Udg$ĊxďktxbXhx @Ё0nK3.E6! ;cȱmd[d"+Y%(\QQ^qÜ=2p lb?r.:֪6=躭EdK.s_-L|K+135:! 2ҖFtZrtǫ.@9EVK¼|s] }-֐o@`7^v-;B62) ^md#co6w( kKO]d5_= ޕJgrWޛu]o]Y!Et5x-+\>o_7#o<_ m;N1%k˳sK֙x6 hۆV ,odkH5iLk鵕.GMi{K𓗚M]kO&>! ~ .ۯ_4ރk](p/OX#='Ezm=ߖGsF&Ozp(f^vzٻ_XE5sF~w}{氆'g+8t3sE[}?,ixCo2FDPW\%{ԇqG|U( >8Hp 5!X&*5р0284X6x8:<؃>@DhN`PL8b QЄRH^GxS SZ ` `  fxh|jR|urAE $XOh({dR0F((\0|d@oXdprh_]HX(phmY0g ƴPx DȈBȈ.hxqzPxxlj0'(. .x8`E %i75H"yb@!,[Ў8. CHh d ɓ㑀XB) @GKP.SGrhV9gaD]d@ɦf)0e Pp0XHXxy `yBCs ʼnYA}@ 0pI5 40PH^:i 009i0` tZJX9I PAƕY8 ͉X0)@` r9@^͉ Imٗyى|ى@ Z 00 IeHʙt4хɠ05!隿9I8b$ AY茔Έ9܉Qa*ɩ {*z I: :Fx*Rx{| =x'6PwA8ȁ:<BG }JC%50.JeJ %`(T8@5YS3e3c7K7ө5kdP{ʁ\"Xh c+ŀ ;e:g &lLPr,R-8}dA̔ Xβ"k( !Y3uJBJTr? "'[hR:jaXVz1Z AƑ7.5ƣ=a:= %K5 IL Mϒ A#1QP;J'?Q3#]0ѶK ๜P,josIk:oz-E QvY:# {:[%e [%/ :Ʒ˴ƻ7b#=P?X 5⻑[2J#piq5Mc7[IlP?x!%F kj1$%*ᰪ0uU;z4"ѫ 9AsosYA^T% 4>9̵PQی1 ZϛM>,ذpGȡ) GPѩchۙ3X+a= ͗) -]:]=P\BAp0 is PѮmmςGݝ=IHHʣɗ m!RA6!`8-zJ\MJIZhlõ8f5nKh(Il|L~U,˲qߦa70iikN3>(imɌߘ[p|yy>sZm)Y~☐ulǶHV9ੌ딨 ѭ?Z,Ɲ0<}⬄ ]*=M ۰q0l,9tH -02;!9Gln 0Z@Q>09qMn0 b[˪~ ^o~:pp> '/_n.n6 Q]hkbc35l%2.?jW_MBflMjnvCqKeoW~a?.7eITT%خMG5`@=1j,ߕ!UK͂o/}/+$lg?:KQ@dȯq?|?Yg #6rڿӛ^mmO\~\~oӯyS4Ic'r>QZ^Y~eivOSC0d !<8:>::6IKM,@  #qsu!'<: 6#GO#XcfZ$Ƶjnwz<8*<*>>8g`ہu `P $HB* NP`@vHɓ9_g x @z2h-$\< @a+  *"r]5b//Ĥmh t9]X6h_T @Р@jZ( <0щv^x\Qۖt"pP=\&R_xةc\APjVYkT "~PE}m x  F6ja"R 3f|BYgьξ? P \-ھK rL\!Ǜ8 WCHA ?EDyDYla>δl,; BD+V)J?p`,/|*cD344:됒0$*ðYl( 4,s&<¿KO{` >Qu @z΂%"@W\N aea( .95gIi"6"L(W8sq49* نuX`hցz F=i-@Ԃ<8 I,u҈I!h6^y5-t,/KFg- Ѓ*\ {#XNc:/* cH6Y-8aDhKI,pUzJ!W TQIz鷍Z;5HNn}\ /h[# @(&V9=O\q'ƒ 8v0R!K{"{L0XIza]" c3]~9N;L`N_Z=,;=j$/1XGl bRu U53ٟ,  WlMʄ4e(D'bJU&" 4¡G%d'd/ 4@PZ*B9 M/")@2 `Qtc!6F21hG.<-o!(ME0:/(# 2;##!I&@JQ q4JteNK0NĎ%ۂIY2,WCe/}ٖbВbӔLZ:q`'وiR3ּLuNGrӜD$]@YMNS;GĉNh@9P$Ї?M(C5E*В"14S90;Fg>ԣ_*a tlBGCf7Ji7t iC,\$穈Dx$'I GX҅ NYњV˃R ()p6bgw[1%7^paܽuc!YNsK+ CNXLq)3gЮd[aKJ^ MS&ȑ r n9:ejZxLI-g1kn!v8(*Zf-/$ B,*gf$b P h% 0%+FpFg2I-qc+ !$`!@.L -PiRo~0 )D2^CM&u +*Ġ 202w11E#FpQ ,G>@No8T<Ϗ:1j2`fVC0qQcݴ6N,%\.OTA, %!2"%R'qڴ1T2 c~PO1*gjOQAp4^I.mE# $O"%"ampHL2% 1 zDd*kh®d&O pԲd(n%-L0C*o 2/r//]d20U)>B nr"12%s2)2-S@25?&zB,"&r8Apq+P]Lu3%`-jc2&@#5-#-Op) u2(:H^{x{T7o8K S :A5Jb,2DZ,O:@5]n|8 ,;:[ZBnE7G,@+:8g(,`U+NMGr ofrK8#t ϲ=3=g}4 RVttFT&(8oT ذ 1(=%=]+RBm!:r4x^xj83Jp%čN"HZE3E00 ( 2*P6h".D++"CF/+([dk4M6R;sO8㳜`V$CzOrQ3yL8R?Hvʳ1 p,ZU3M 0~ ]T8FE>@:lTSVLbf<"80",cT3\VN)U342'^ b2U*GPP#TwnQ 9f8@FKC=bKIn) Xz&\0?'r*.IcDDD-B(LP L66pvbH"eB`qC@`^ax*nf(H-~d ( hOf̡>+$bQ Object Support in Oracle Programming Environments

4 Object Support in Oracle Programming Environments

In an Oracle database, you can create object types with SQL data definition language (DDL) commands, and you can manipulate objects with SQL data manipulation language (DML) commands. Object support is built into Oracle application programming environments.

This chapter discusses the following topics:

SQL

Oracle SQL DDL provides the following support for object types:

  • Defining object types, nested tables, and arrays

  • Specifying privileges

  • Specifying table columns of object types

  • Creating object tables

Oracle SQL DML provides the following support for object types:

  • Querying and updating objects and collections

  • Manipulating REFs


    See Also:

    For a complete description of Oracle SQL syntax, see Oracle Database SQL Reference

PL/SQL

Object types and subtypes can be used in PL/SQL procedures and functions in most places where built-in types can appear.

The parameters and variables of PL/SQL functions and procedures can be of object types.

You can implement the methods associated with object types in PL/SQL. These methods (functions and procedures) reside on the server as part of a user's schema.


See Also:

For a complete description of PL/SQL, see the Oracle Database PL/SQL User's Guide and Reference

Oracle Call Interface (OCI)

OCI is a set of C library functions that applications can use to manipulate data and schemas in an Oracle database. OCI supports both traditional 3GL and object-oriented techniques for database access, as explained in the following sections.

An important component of OCI is a set of calls to manage a workspace called the object cache. The object cache is a memory block on the client side that allows programs to store entire objects and to navigate among them without additional round trips to the server.

The object cache is completely under the control and management of the application programs using it. The Oracle server has no access to it. The application programs using it must maintain data coherency with the server and protect the workspace against simultaneous conflicting access.

OCI provides functions to

  • Access objects on the server using SQL.

  • Access, manipulate and manage objects in the object cache by traversing pointers or REFs.

  • Convert Oracle dates, strings and numbers to C data types.

  • Manage the size of the object cache's memory.

OCI improves concurrency by allowing individual objects to be locked. It improves performance by supporting complex object retrieval.

OCI developers can use the object type translator to generate the C datatypes corresponding to a Oracle object types.


See Also:

Oracle Call Interface Programmer's Guide for more information about using objects with OCI

Associative Access in OCI Programs

Traditionally, 3GL programs manipulate data stored in a relational database by executing SQL statements and PL/SQL procedures. Data is usually manipulated on the server without incurring the cost of transporting the data to the client(s). OCI supports this associative access to objects by providing an API for executing SQL statements that manipulate object data. Specifically, OCI enables you to:

  • Execute SQL statements that manipulate object data and object type schema information

  • Pass object instances, object references (REFs), and collections as input variables in SQL statements

  • Return object instances, REFs, and collections as output of SQL statement fetches

  • Describe the properties of SQL statements that return object instances, REFs, and collections

  • Describe and execute PL/SQL procedures or functions with object parameters or results

  • Synchronize object and relational functionality through enhanced commit and rollback functions

See "Associative Access in Pro*C/C++".

Navigational Access in OCI Programs

In the object-oriented programming paradigm, applications model their real-world entities as a set of inter-related objects that form graphs of objects. The relationships between objects are implemented as references. An application processes objects by starting at some initial set of objects, using the references in these initial objects to traverse the remaining objects, and performing computations on each object. OCI provides an API for this style of access to objects, known as navigational access. Specifically, OCI enables you to:

  • Cache objects in memory on the client machine

  • De-reference an object reference and pin the corresponding object in the object cache. The pinned object is transparently mapped in the host language representation.

  • Notify the cache when the pinned object is no longer needed

  • Fetch a graph of related objects from the database into the client cache in one call

  • Lock objects

  • Create, update, and delete objects in the cache

  • Flush changes made to objects in the client cache to the database

See "Navigational Access in Pro*C/C++".

Object Cache

To support high-performance navigational access of objects, OCI runtime provides an object cache for caching objects in memory. The object cache supports references (REFs) to database objects in the object cache, the database objects can be identified (that is, pinned) through their references. Applications do not need to allocate or free memory when database objects are loaded into the cache, because the object cache provides transparent and efficient memory management for database objects.

Also, when database objects are loaded into the cache, they are transparently mapped into the host language representation. For example, in the C programming language, the database object is mapped to its corresponding C structure. The object cache maintains the association between the object copy in the cache and the corresponding database object. Upon transaction commit, changes made to the object copy in the cache are propagated automatically to the database.

The object cache maintains a fast look-up table for mapping REFs to objects. When an application de-references a REF and the corresponding object is not yet cached in the object cache, the object cache automatically sends a request to the server to fetch the object from the database and load it into the object cache. Subsequent de-references of the same REF are faster because they become local cache access and do not incur network round-trips. To notify the object cache that an application is accessing an object in the cache, the application pins the object; when it is finished with the object, it unpins it. The object cache maintains a pin count for each object in the cache. The count is incremented upon a pin call and decremented upon an unpin call. When the pin count goes to zero, it means the object is no longer needed by the application. The object cache uses a least-recently used (LRU) algorithm to manage the size of the cache. When the cache reaches the maximum size, the LRU algorithm frees candidate objects with a pin count of zero.

Building an OCI Program That Manipulates Objects

When you build an OCI program that manipulates objects, you must complete the following general steps:

  1. Define the object types that correspond to the application objects.

  2. Execute the SQL DDL statements to populate the database with the necessary object types.

  3. Represent the object types in the host language format.

    For example, to manipulate instances of the object types in a C program, you must represent these types in the C host language format. You can do this by representing the object types as C structs. You can use a tool provided by Oracle called the Object Type Translator (OTT) to generate the C mapping of the object types. The OTT puts the equivalent C structs in header (*.h) files. You include these *.h files in the *.c files containing the C functions that implement the application.

  4. Construct the application executable by compiling and linking the application's *.c files with the OCI library.


    See Also:

    Oracle Call Interface Programmer's Guide for tips and techniques for using OCI program effectively with objects

Defining User-Defined Constructors in C

When defining a user-defined constructor in C, you must specify SELF (and you may optionally specify SELF TDO) in the PARAMETERS clause. On entering the C function, the attributes of the C structure that the object maps to are all initialized to NULL. The value returned by the function is mapped to an instance of the user-defined type. Example 4-1 shows how to define a user-defined constructor in C.

Example 4-1 Defining a User-Defined Constructor in C

CREATE LIBRARY person_lib TRUSTED AS STATIC
/

CREATE TYPE person AS OBJECT
  (  name VARCHAR2(30),
     CONSTRUCTOR FUNCTION person(SELF IN OUT NOCOPY person, name VARCHAR2) 
         RETURN SELF AS RESULT);
/

CREATE TYPE BODY person IS
    CONSTRUCTOR FUNCTION person(SELF IN OUT NOCOPY person, name VARCHAR2) 
         RETURN SELF AS RESULT
    IS EXTERNAL NAME "cons_person_typ" LIBRARY person_lib WITH CONTEXT
    PARAMETERS(context, SELF, name OCIString, name INDICATOR sb4); 
END;/

The SELF parameter is mapped like an IN parameter, so in the case of a NOT FINAL type, it is mapped to (dvoid *), not (dvoid **).

The return value's TDO must match the TDO of SELF and is therefore implicit. The return value can never be null, so the return indicator is implicit as well.

Pro*C/C++

The Oracle Pro*C/C++ precompiler allows programmers to use user-defined datatypes in C and C++ programs.

Pro*C developers can use the Object Type Translator to map Oracle object types and collections into C datatypes to be used in the Pro*C application.

Pro*C provides compile time type checking of object types and collections and automatic type conversion from database types to C datatypes.

Pro*C includes an EXEC SQL syntax to create and destroy objects and offers two ways to access objects in the server:

  • SQL statements and PL/SQL functions or procedures embedded in Pro*C programs.

  • An interface to the object cache (described under "Oracle Call Interface (OCI)"), where objects can be accessed by traversing pointers, then modified and updated on the server.


    See Also:

    For a complete description of the Pro*C precompiler, see Pro*C/C++ Programmer's Guide.

Associative Access in Pro*C/C++

For background information on associative access, see "Associative Access in OCI Programs".

Pro*C/C++ offers the following capabilities for associative access to objects:

  • Support for transient copies of objects allocated in the object cache

  • Support for transient copies of objects referenced as input host variables in embedded SQL INSERT, UPDATE, and DELETE statements, or in the WHERE clause of a SELECT statement

  • Support for transient copies of objects referenced as output host variables in embedded SQL SELECT and FETCH statements

  • Support for ANSI dynamic SQL statements that reference object types through the DESCRIBE statement, to get the object's type and schema information

Navigational Access in Pro*C/C++

For background information on navigational access, see "Navigational Access in OCI Programs".

Pro*C/C++ offers the following capabilities to support a more object-oriented interface to objects:

  • Support for de-referencing, pinning, and optionally locking an object in the object cache using an embedded SQL OBJECT DEREF statement

  • Allowing a Pro*C/C++ user to inform the object cache when an object has been updated or deleted, or when it is no longer needed, using embedded SQL OBJECT UPDATE, OBJECT DELETE, and OBJECT RELEASE statements

  • Support for creating new referenceable objects in the object cache using an embedded SQL OBJECT CREATE statement

  • Support for flushing changes made in the object cache to the server with an embedded SQL OBJECT FLUSH statement

Converting Between Oracle Types and C Types

The C representation for objects that is generated by the Oracle Type Translator (OTT) uses OCI types whose internal details are hidden, such as OCIString and OCINumber for scalar attributes. Collection types and object references are similarly represented using OCITable, OCIArray, and OCIRef types. While using these opaque types insulates you from changes to their internal formats, using such types in a C or C++ application is cumbersome. Pro*C/C++ provides the following ease-of-use enhancements to simplify use of OCI types in C and C++ applications:

  • Object attributes can be retrieved and implicitly converted to C types with the embedded SQL OBJECT GET statement.

  • Object attributes can be set and converted from C types with the embedded SQL OBJECT SET statement.

  • Collections can be mapped to a host array with the embedded SQL COLLECTION GET statement. Furthermore, if the collection is comprised of scalar types, then the OCI types can be implicitly converted to a compatible C type.

  • Host arrays can be used to update the elements of a collection with the embedded SQL COLLECTION SET statement. As with the COLLECTION GET statement, if the collection is comprised of scalar types, C types are implicitly converted to OCI types.

Oracle Type Translator (OTT)

The Oracle type translator (OTT) is a program that automatically generates C language structure declarations corresponding to object types. OTT makes it easier to use the Pro*C precompiler and the OCI server access package.


See Also:

For complete information about OTT, see Oracle Call Interface Programmer's Guide and Pro*C/C++ Programmer's Guide.

Oracle C++ Call Interface (OCCI)

The Oracle C++ Call Interface (OCCI) is a C++ API that enables you to use the object-oriented features, native classes, and methods of the C++ programing language to access the Oracle database.

The OCCI interface is modeled on the JDBC interface and, like the JDBC interface, is easy to use. OCCI itself is built on top of OCI and provides the power and performance of OCI using an object-oriented paradigm.

OCI is a C API to the Oracle database. It supports the entire Oracle feature set and provides efficient access to both relational and object data, but it can be challenging to use—particularly if you want to work with complex, object datatypes. Object types are not natively supported in C, and simulating them in C is not easy. OCCI addresses this by providing a simpler, object-oriented interface to the functionality of OCI. It does this by defining a set of wrappers for OCI. By working with these higher-level abstractions, developers can avail themselves of the underlying power of OCI to manipulate objects in the server through an object-oriented interface that is significantly easier to program.

The Oracle C++ Call Interface, OCCI, can be roughly divided into three sets of functionalities, namely:

  • Associative relational access

  • Associative object access

  • Navigational access

OCCI Associative Relational and Object Interfaces

The associative relational API and object classes provide SQL access to the database. Through these interfaces, SQL is executed on the server to create, manipulate, and fetch object or relational data. Applications can access any datatype on the server, including the following:

  • Large objects

  • Objects/Structured types

  • Arrays

  • References

The OCCI Navigational Interface

The navigational interface is a C++ interface that lets you seamlessly access and modify object-relational data in the form of C++ objects without using SQL. The C++ objects are transparently accessed and stored in the database as needed.

With the OCCI navigational interface, you can retrieve an object and navigate through references from that object to other objects. Server objects are materialized as C++ class instances in the application cache.

An application can use OCCI object navigational calls to perform the following functions on the server's objects:

  • Create, access, lock, delete, and flush objects

  • Get references to the objects and navigate through them


    See Also:

    Oracle C++ Call Interface Programmer's Guide for a complete account of how to build applications with the Oracle C++ API

Oracle Objects For OLE (OO4O)

Oracle Objects for OLE (OO4O) provides full support for accessing and manipulating instances of REFs, value instances, variable-length arrays (VARRAYs), and nested tables in an Oracle database server.

On Windows systems, you can use Oracle Objects for OLE (OO4O) to write object-oriented database programs in Visual Basic or other environments that support the COM protocol, such as Excel, ActiveX, and Active Server Pages.


See Also:

The "OO4O Automation Server Reference" section of the Oracle Objects for OLE online help or Oracle Objects for OLE Developer's Guide online documentation for detailed information and examples on using OO4O with Oracle objects

Figure 4-1 illustrates the containment hierarchy for value instances of all types in OO4O.

Figure 4-1 Supported Oracle Datatypes

Description of adobj017.gif follows


Instances of these types can be fetched from the database or passed as input or output variables to SQL statements and PL/SQL blocks, including stored procedures and functions. All instances are mapped to COM Automation Interfaces that provide methods for dynamic attribute access and manipulation. These interfaces may be obtained from:

  • The value property of an OraField object in a dynaset

  • The value property of an OraParameter object used as an input or an output parameter in SQL Statements or PL/SQL blocks

  • An attribute of an object (REF)

  • An element in a collection (varray or a nested table)

Representing Objects in Visual Basic (OraObject)

The OraObject interface is a representation of an Oracle embedded object or a value instance. It contains a collection interface (OraAttributes) for accessing and manipulating (updating and inserting) individual attributes of a value instance. Individual attributes of an OraAttributes collection interface can be accessed by using a subscript or the name of the attribute.

The following Visual Basic example illustrates how to access attributes of the Address object in the person_tab table:


Dim Address OraObject
Set Person =
  OraDatabase.CreateDynaset("select * from person_tab", 0&)
Set Address = Person.Fields("Addr").Value
Msgbox Address.Zip
Msgbox.Address.City

Representing REFs in Visual Basic (OraRef)

The OraRef interface represents an Oracle object reference (REF) as well as referenceable objects in client applications. The object attributes are accessed in the same manner as attributes of an object represented by the OraObject interface. OraRef is derived from an OraObject interface by means of the containment mechanism in COM. REF objects are updated and deleted independent of the context they originated from, suLmch as dynasets. The OraRef interface also encapsulates the functionality for navigating through graphs of objects utilizing the Complex Object Retrieval Capability (COR) in OCI.


See Also:

Oracle Call Interface Programmer's Guide for tips and techniques for using OCI program effectively with objects

Representing VARRAYs and Nested Tables in Visual Basic (OraCollection)

The OraCollection interface provides methods for accessing and manipulating Oracle collection types, namely variable-length arrays (VARRAYs) and nested tables in OO4O. Elements contained in a collection are accessed by subscripts.

The following Visual Basic example illustrates how to access attributes of the EnameList object from the department table:

Java: JDBC, Oracle SQLJ, JPublisher, and SQLJ Object Types

Java has emerged as a powerful, modern object-oriented language that provides developers with a simple, efficient, portable, and safe application development platform. Oracle provides two ways to integrate Oracle object features with Java: JDBC and Oracle SQLJ. These interfaces enable you both to access SQL data from Java and to provide persistent database storage for Java objects.

For an example of using Java APIs with Oracle objects, see the Oracle by Example Series available on the Oracle Technology Network (OTN) Web site:

http://otn.oracle.com/products/oracle9i/htdocs/9iobe/OBE9i-Public/obe-dev/html/objects/objects.htm

You can use the followings steps to navigate to the Oracle objects module in the Oracle by Example Series.

  • Go to http://www.oracle.com/technology/

  • Select Oracle Database under Products from the menu on the left side of the page

  • Select Oracle9i Database Release 1 under Previous Releases on the right side of the page

  • Under Technical Information, select Oracle9i by Example Series

  • Select Build Application Components from the menu on the left side of the page

  • Select the Using Objects to Build an Online Product Catalog example

You can also search for Using Objects to Build an Online Product Catalog on the OTN Web site at http://www.oracle.com/technology/.

JDBC Access to Oracle Object Data

JDBC (Java Database Connectivity) is a set of Java interfaces to the Oracle server. Oracle provides tight integration between objects and JDBC. You can map SQL types to Java classes with considerable flexibility.

Oracle JDBC:

  • Allows access to objects and collection types (defined in the database) in Java programs through dynamic SQL.

  • Translates types defined in the database into Java classes through default or customizable mappings.

Version 2.0 of the JDBC specification supports object-relational constructs such as user-defined (object) types. JDBC materializes Oracle objects as instances of particular Java classes. Using JDBC to access Oracle objects involves creating the Java classes for the Oracle objects and populating these classes. You can either:

  • Let JDBC materialize the object as a STRUCT. In this case, JDBC creates the classes for the attributes and populates them for you.

  • Manually specify the mappings between Oracle objects and Java classes; that is, customize your Java classes for object data. The driver then populates the customized Java classes that you specify, which imposes a set of constraints on the Java classes. To satisfy these constraints, you can choose to define your classes according to either the SQLData interface or the ORAData interface.


    See Also:

    For complete information about JDBC, see the Oracle Database JDBC Developer's Guide and Reference.

SQLJ Access to Oracle Object Data

SQLJ provides access to server objects using SQL statements embedded in the Java code:

  • You can use user-defined types in Java programs.

  • You can use JPublisher to map Oracle object and collection types into Java classes to be used in the application.

  • The object types and collections in the SQL statements are checked at compile time.


    See Also:

    For complete information about SQLJ, see the Oracle Database Java Developer's Guide.

Choosing a Data Mapping Strategy

Oracle SQLJ supports either strongly typed or weakly typed Java representations of object types, reference types (REFs), and collection types (varrays and nested tables) to be used in iterators or host expressions.

Strongly typed representations use a custom Java class that corresponds to a particular object type, REF type, or collection type and must implement the interface oracle.sql.ORAData. The Oracle JPublisher utility can automatically generate such custom Java classes.

Weakly typed representations use the class oracle.sql.STRUCT (for objects), oracle.sql.REF (for references), or oracle.sql.ARRAY (for collections).

Using JPublisher to Create Java Classes for JDBC and SQLJ Programs

Oracle lets you map Oracle object types, reference types, and collection types to Java classes and preserve all the benefits of strong typing. You can:

  • Use JPublisher to automatically generate custom Java classes and use those classes without any change.

  • Subclass the classes produced by JPublisher to create your own specialized Java classes.

  • Manually code custom Java classes without using JPublisher if the classes meet the requirements stated in the Oracle Database JPublisher User's Guide.

We recommend that you use JPublisher and subclass when the generated classes do not do everything you need.

What JPublisher Produces for a User-Defined Object Type

When you run JPublisher for a user-defined object type, it automatically creates the following:

  • A custom object class to act as a type definition to correspond to your Oracle object type

    This class includes getter and setter methods for each attribute. The method names are of the form getXxx() and setXxx() for attribute xxx.

    Also, you can optionally instruct JPublisher to generate wrapper methods in your class that invoke the associated Oracle object methods executing in the server.

  • A related custom reference class for object references to your Oracle object type

    This class includes a getValue() method that returns an instance of your custom object class, and a setValue() method that updates an object value in the database, taking as input an instance of the custom object class.

When you run JPublisher for a user-defined collection type, it automatically creates the following:

  • A custom collection class to act as a type definition to correspond to your Oracle collection type

    This class includes overloaded getArray() and setArray() methods to retrieve or update a collection as a whole, a getElement() method and setElement() method to retrieve or update individual elements of a collection, and additional utility methods.

JPublisher-produced custom Java classes in any of these categories implement the ORAData interface and the getFactory() method.


See Also:

The Oracle Database JPublisher User's Guide for more information about using JPublisher.

Java Object Storage

JPublisher enables you to construct Java classes that map to existing SQL types. You can then access the SQL types from a Java application using JDBC.

You can also go in the other direction. That is, you can create SQL types that map to existing Java classes. This capability enables you to provide persistent storage for Java objects. Such SQL types are called SQL types of Language Java, or SQLJ object types. They can be used as the type of an object, an attribute, a column, or a row in an object table. You can navigationally access objects of such types—Java objects—through either object references or foreign keys, and you can query and manipulate such objects from SQL.

You create SQLJ types with a CREATE TYPE statement as you do other user-defined SQL types. For SQLJ types, two special elements are added to the CREATE TYPE statement:

  • An EXTERNAL NAME phrase, used to identify the Java counterpart for each SQLJ attribute and method and the Java class corresponding to the SQLJ type itself

  • A USING clause, to specify how the SQLJ type is to be represented to the server. The USING clause specifies the interface used to retrieve a SQLJ type and the kind of storage.

For example:

Example 4-2 Mapping SQL Types to Java Classes

CREATE TYPE full_address AS OBJECT (a NUMBER);
/

CREATE OR REPLACE TYPE person_t AS OBJECT
  EXTERNAL NAME 'Person' LANGUAGE JAVA
  USING SQLData (
    ss_no NUMBER (9) EXTERNAL NAME 'socialSecurityNo',
    name varchar(100) EXTERNAL NAME 'name',
    address full_address EXTERNAL NAME 'addrs',
    birth_date date EXTERNAL NAME 'birthDate',
    MEMBER FUNCTION age  RETURN NUMBER EXTERNAL NAME 'age () return int',
    MEMBER FUNCTION addressf RETURN full_address
      EXTERNAL NAME 'get_address () return long_address',
    STATIC function createf RETURN person_t EXTERNAL NAME 'create () 
         return Person',
    STATIC function createf (name VARCHAR2, addrs full_address, bDate DATE)
      RETURN person_t EXTERNAL NAME 'create (java.lang.String, Long_address,
      oracle.sql.date) return Person',
    ORDER member FUNCTION compare (in_person person_t) RETURN NUMBER
      EXTERNAL NAME 'isSame (Person) return int')
/

SQLJ types use the corresponding Java class as the body of the type; you do not specify a type body in SQL to contain implementations of the type's methods as you do with ordinary object types.

Representing SQLJ Types to the Server

How a SQLJ type is represented to the server and stored depends on the interfaces implemented by the corresponding Java class. Currently, Oracle supports a representation of SQLJ types only for Java classes that implement a SQLData or ORAData interface. These are represented to the server and are accessible through SQL. A representation for Java classes that implement the java.io.Serializable interface is not currently supported.

In a SQL representation, the attributes of the type are stored in columns like attributes of ordinary object types. With this representation, all attributes are public because objects are accessed and manipulated through SQL statements, but you can use triggers and constraints to ensure the consistency of the object data.

For a SQL representation, the USING clause must specify either SQLData or ORAData, and the corresponding Java class must implement one of those interfaces. The EXTERNAL NAME clause for attributes is optional.

Creating SQLJ Object Types

The SQL statements to create SQLJ types and specify their mappings to Java are placed in a file called a deployment descriptor. Related SQL constraints and privileges are also specified in this file. The types are created when the file is executed.

Below is an overview of the process of creating SQL versions of Java types/classes:

  1. Design the Java types.

  2. Generate the Java classes.

  3. Create the SQLJ object type statements.

  4. Construct the JAR file. This is a single file that contains all the classes needed.

  5. Using the loadjava utility, install the Java classes defined in the JAR file.

  6. Execute the statements to create the SQLJ object types.

Additional Notes About Mapping

The following are additional notes to consider when mapping of Java classes to SQL types:

  • You can map a SQLJ static function to a user-defined constructor in the Java class. The return value of this function is of the user-defined type in which the function is locally defined.

  • Java static variables are mapped to SQLJ static methods that return the value of the corresponding static variable identified by EXTERNAL NAME. The EXTERNAL NAME clause for an attribute is optional with a SQLData or ORAData representation.

  • Every attribute in a SQLJ type of a SQL representation must map to a Java field, but not every Java field must be mapped to a corresponding SQLJ attribute: you can omit Java fields from the mapping.

  • You can omit classes: you can map a SQLJ type to a non-root class in a Java class hierarchy without also mapping SQLJ types to the root class and intervening superclasses. Doing this enables you to hide the superclasses while still including attributes and methods inherited from them.

    However, you must preserve the structural correspondence between nodes in a class hierarchy and their counterparts in a SQLJ type hierarchy. In other words, for two Java classes j_A and j_B that are related through inheritance and are mapped to two SQL types s_A and s_B, respectively, there must be exactly one corresponding node on the inheritance path from s_A to s_B for each node on the inheritance path from j_A to j_B.

  • You can map a Java class to multiple SQLJ types as long as you do not violate the restriction in the preceding paragraph. In other words, no two SQLJ types mapped to the same Java class can have a common supertype ancestor.

  • If all Java classes are not mapped to SQLJ types, it is possible that an attribute of a SQLJ object type might be set to an object of an unmapped Java class. Specifically, to a class occurring above or below the class to which the attribute is mapped in an inheritance hierarchy. If the object's class is a superclass of the attribute's type/class, an error is raised. If it is a subclass of the attribute's type/class, the object is mapped to the most specific type in its hierarchy for which a SQL mapping exists


See Also:

The Oracle Database JPublisher User's Guide for JPublisher examples of object mapping

Evolving SQLJ Types

The ALTER TYPE statement enables you to evolve a type by, for example, adding or dropping attributes or methods.

When a SQLJ type is evolved, an additional validation is performed to check the mapping between the class and the type. If the class and the evolved type match, the type is marked valid. Otherwise, the type is marked as pending validation.

Being marked as pending validation is not the same as being marked invalid. A type that is pending validation can still be manipulated with ALTER TYPE and GRANT statements, for example.

If a type that has a SQL representation is marked as pending evaluation, you can still access tables of that type using any DML or SELECT statement that does not require a method invocation.

You cannot, however, execute DML or SELECT statements on tables of a type that has a serializable representation and has been marked as pending validation. Data of a serializable type can be accessed only navigationally, through method invocations. These are not possible with a type that is pending validation. However, you can still re-evolve the type until it passes validation.

See "Type Evolution".

Constraints

For SQLJ types having a SQL representation, the same constraints can be defined as for ordinary object types.

Constraints are defined on tables, not on types, and are defined at the column level. The following constraints are supported for SQLJ types having a SQL representation:

  • Unique constraints

  • Primary Key

  • Check constraints

  • NOT NULL constraints on attributes

  • Referential constraints

The IS OF TYPE constraint on column substitutability is supported, too, for SQLJ types having a SQL representation. See "Constraining Substitutability".

Querying SQLJ Objects

SQLJ types can be queried just like ordinary SQL object types. Methods called in a SELECT statement must not attempt to change attribute values.

Inserting Java Objects

Inserting a row in a table containing a column of a SQLJ type requires a call to the type's constructor function to create a Java object of that type.

The implicit, system-generated constructor can be used, or a static function can be defined that maps to a user-defined constructor in the Java class.

Updating SQLJ Objects

SQLJ objects can be updated either by using an UPDATE statement to modify the value of one or more attributes, or by invoking a method that updates the attributes and returns SELF—that is, returns the object itself with the changes made.

For example, suppose that raise() is a member function that increments the salary field/attribute by a specified amount and returns SELF. The following statement gives every employee in the object table employee_objtab a raise of 1000:

UPDATE employee_objtab SET c=c.raise(1000);

A column of a SQLJ type can be set to NULL or to another column using the same syntax as for ordinary object types. For example, the following statement assigns column d to column c:

UPDATE employee_reltab SET c=d;

Defining User-Defined Constructors in Java

When you implement a user-defined constructor in Java, the string supplied as the implementing routine must correspond to a static function. For the return type of the function, specify the Java type mapped to the SQL type.

Example 4-3 is an example of a type declaration that involves a user-defined constructor implemented in Java.

Example 4-3 Defining a User-Defined Constructor in Java

CREATE TYPE person1_typ AS OBJECT 
 EXTERNAL NAME 'pkg1.J_Person' LANGUAGE JAVA 
 USING SQLData( 
  name VARCHAR2(30), 
  age NUMBER,
  CONSTRUCTOR FUNCTION person1_typ(SELF IN OUT NOCOPY person1_typ, name VARCHAR2,
                                   age NUMBER) RETURN SELF AS RESULT
  AS LANGUAGE JAVA 
    NAME 'pkg1.J_Person.J_Person(java.lang.String, int) return J_Person')
/

XML

XMLType views wrap existing relational and object-relational data in XML formats. These views are similar to object views. Each row of an XMLType view corresponds to an XMLType instance. The object identifier for uniquely identifying each row in the view can be created using an expression such as extract() on the XMLType value.


See Also:

Oracle XML DB Developer's Guide for information and examples on using XML with Oracle objects

PKuVLPKpUIOEBPS/preface.htmt Preface

Preface

Oracle Database Application Developer's Guide - Object-Relational Features describes how to use the object-relational features of the Oracle Server, 10g release 2 (10.2). Information in this guide applies to versions of the Oracle Server that run on all platforms, and does not include system-specific information.

Intended Audience

Oracle Database Application Developer's Guide - Object-Relational Features is intended for programmers developing new applications or converting existing applications to run in the Oracle environment. The object-relational features are often used in content management, data warehousing, data/information integration, and similar applications that deal with complex structured data. The object views feature can be valuable when writing new C++, Java, or XML applications on top of an existing relational schema.

This guide assumes that you have a working knowledge of application programming and that you are familiar with the use of Structured Query Language (SQL) to access information in relational database systems.

Documentation Accessibility

Our goal is to make Oracle products, services, and supporting documentation accessible, with good usability, to the disabled community. To that end, our documentation includes features that make information available to users of assistive technology. This documentation is available in HTML format, and contains markup to facilitate access by the disabled community. Accessibility standards will continue to evolve over time, and Oracle is actively engaged with other market-leading technology vendors to address technical obstacles so that our documentation can be accessible to all of our customers. For more information, visit the Oracle Accessibility Program Web site at

http://www.oracle.com/accessibility/

Accessibility of Code Examples in Documentation

Screen readers may not always correctly read the code examples in this document. The conventions for writing code require that closing braces should appear on an otherwise empty line; however, some screen readers may not always read a line of text that consists solely of a bracket or brace.

Accessibility of Links to External Web Sites in Documentation

This documentation may contain links to Web sites of other companies or organizations that Oracle does not own or control. Oracle neither evaluates nor makes any representations regarding the accessibility of these Web sites.

TTY Access to Oracle Support Services

Oracle provides dedicated Text Telephone (TTY) access to Oracle Support Services within the United States of America 24 hours a day, seven days a week. For TTY support, call 800.446.2398.

Structure

This document contains:

Chapter 1, "Introduction to Oracle Objects"

Introduces the key features and explains the advantages of the object-relational model.

Chapter 2, "Basic Components of Oracle Objects"

Explains the basic concepts and terminology that you need to work with Oracle Objects.

Chapter 3, "Support for Collection Datatypes"

Discusses collection datatypes and operations on collection datatypes.

Chapter 4, "Object Support in Oracle Programming Environments"

Summarizes the object-relational features in SQL and PL/SQL; Oracle Call Interface (OCI); Pro*C/C++; Oracle Objects For OLE; and Java, JDBC, and Oracle SQLJ. The information in this chapter is high-level, for education and planning.

Chapter 5, "Applying an Object Model to Relational Data"

Explains object views, which allow you to develop object-oriented applications without changing the underlying relational schema.

Chapter 6, "Managing Oracle Objects"

Explains how to perform essential operations with objects and object types.

Chapter 7, "Advanced Topics for Oracle Objects"

Discusses features that you might need to manage storage and performance as you scale up an object-oriented application.

Chapter 8, "Design Considerations for Oracle Objects"

Explains the implementation and performance characteristics of the Oracle object-relational model.

Appendix A, "Sample Application Using Object-Relational Features"

Demonstrates how a relational program can be rewritten as an object-oriented one, schema and all.

Related Documents

For more information, see these Oracle resources:

Many of the examples in this book use the sample schemas of the seed database, which is installed by default when you install Oracle. Refer to Oracle Database Sample Schemas for information on how these schemas were created and how you can use them yourself.

Printed documentation is available for sale in the Oracle Store at

http://oraclestore.oracle.com/

To download free release notes, installation documentation, white papers, or other collateral, please visit the Oracle Technology Network (OTN). You must register online before using OTN; registration is free and can be done at

http://www.oracle.com/technology/membership/

If you already have a username and password for OTN, then you can go directly to the documentation section of the OTN Web site at

http://www.oracle.com/technology/documentation/

For information on additional books

http://www.oracle.com/technology/books/10g_books.html

Conventions

This section describes the conventions used in the text and code examples of this documentation set. It describes:

Conventions in Text

We use various conventions in text to help you more quickly identify special terms. The following table describes those conventions and provides examples of their use.

Convention Meaning Example
Bold Bold typeface indicates terms that are defined in the text or terms that appear in a glossary, or both. When you specify this clause, you create an index-organized table.
Italics Italic typeface indicates book titles or emphasis. Oracle Database Concepts

Ensure that the recovery catalog and target database do not reside on the same disk.

UPPERCASE monospace (fixed-width) font Uppercase monospace typeface indicates elements supplied by the system. Such elements include parameters, privileges, datatypes, RMAN keywords, SQL keywords, SQL*Plus or utility commands, packages and methods, as well as system-supplied column names, database objects and structures, usernames, and roles. You can specify this clause only for a NUMBER column.

You can back up the database by using the BACKUP command.

Query the TABLE_NAME column in the USER_TABLES data dictionary view.

Use the DBMS_STATS.GENERATE_STATS procedure.

lowercase monospace (fixed-width) font Lowercase monospace typeface indicates executables, filenames, directory names, and sample user-supplied elements. Such elements include computer and database names, net service names, and connect identifiers, as well as user-supplied database objects and structures, column names, packages and classes, usernames and roles, program units, and parameter values.

Note: Some programmatic elements use a mixture of UPPERCASE and lowercase. Enter these elements as shown.

Enter sqlplus to start SQL*Plus.

The password is specified in the orapwd file.

Back