Oracle8 Concepts Release 8.0 A58227-01 |
Library | Product | Contents | Index

# 11
User-Defined Datatypes (Objects Option)

We must learn to explore all the options and possibilities that confront us in a complex and rapidly changing world.

James William Fulbright, Speech in the Senate (1964)

The Objects option allows users to define datatypes that model the structure and behavior of the data in their applications.

This chapter contains the following major sections:

- Introduction
- User-Defined Datatypes
- Application Interfaces

  Attention: The features described in this chapter are available only if you have purchased Oracle8 Enterprise Edition with the Objects Option. Wherever the term Oracle server appears in this chapter it refers to the Oracle8 Enterprise Edition with the Objects Option. See Getting to Know Oracle8 and the Oracle8 Enterprise Edition for information about the features and options available with Oracle8 Enterprise Edition.

## Introduction

Relational database management systems (RDBMSs) are the standard tool for managing business data. They provide fast, efficient, and completely reliable access to huge amounts of data for millions of businesses around the world every day.

The Objects option makes Oracle an object-relational database management system (ORDBMS), which means that users can define additional kinds of data - specifying both the structure of the data and the ways of operating on it - and use these types within the relational model. This approach adds value to the data stored in a database.

Oracle with the Objects option stores structured business data in its natural form and allows applications to retrieve it that way. For that reason it works efficiently with applications developed using object-oriented programming techniques.

Oracle's support for user-defined datatypes makes it easier for application developers to work with complex data like images, audio, and video.

### Complex Data Models

The Oracle server allows you to define complex business models in SQL and make them part of your database schema. Applications that manage and share your data need only contain the application logic, not the data logic.

#### An Example

For example, your firm may use purchase orders to organize its purchasing, accounts payable, shipping, and accounts receivable functions.

A purchase order contains an associated supplier or customer and an indefinite number of line items. In addition, applications often need dynamically computed status information about purchase orders. For example, you may need the current value of the shipped or unshipped line items.

Later sections of this chapter show how you can define a schema object, called an object type, that serves as a template for all purchase order data in your applications. An object type specifies the elements, called attributes, that make up a structured data unit like a purchase order. Some attributes, such as the list of line items, may be other structured data units. The object type also specifies the operations, called methods, you can perform on the data unit, such as determining the total value of a purchase order.

You can create purchase orders that match the template and store them in table columns, just as you would numbers or dates.

You can also store purchase orders in object tables, where each row of the table corresponds to a single purchase order and the table columns are the purchase order's attributes.

Since the logic of the purchase order's structure and behavior is in your schema, your applications don't need to know the details and don't have to keep up with most changes.

Oracle uses schema information about object types to achieve substantial transmission efficiencies. A client-side application can request a purchase order from the server and receive all the relevant data in a single transmission. The application can then, without knowing storage locations or implementation details, navigate among related data items without further transmissions from the server.

### Multimedia Datatypes

Many efficiencies of database systems arise from their optimized management of basic datatypes like numbers, dates, and characters. Facilities exist for comparing values, determining their distributions, building efficient indexes, and performing other optimizations.

Text, video, sound, graphics, and spatial data are examples of important business entities that don't fit neatly into those basic types. Oracle with the Objects option supports modeling and implementation of these complex datatypes.

## User-Defined Datatypes

Chapter 10, "Built-In Datatypes" describes Oracle's built-in datatypes. The Objects option adds two categories of user-defined datatypes:

- object types
- collection types

User-defined datatypes use the built-in datatypes and other user-defined datatypes as the building blocks for datatypes that model the structure and behavior of data in applications.

User-defined types are schema objects. Their use is subject to the same kinds of administrative control as other schema objects (see Chapter 12, "Using User-Defined Datatypes").

### Object Types

Object types are abstractions of the real-world entities - for example, purchase orders - that application programs deal with. An object type is a schema object with three kinds of components:

- A name, which serves to identify the object type uniquely within that schema.
- Attributes, which model the structure and state of the real world entity. Attributes are built-in types or other user-defined types.
- Methods, which are functions or procedures written in PL/SQL and stored in the database, or written in a language like C and stored externally. Methods implement operations the application can perform on the real world entity.

An object type is a template. A structured data unit that matches the template is called an object.

#### Purchase Order Example

Here is an example of how you might define object types called `external_person`, `lineitem`, and `purchase_order`.

The object types `external_person` and `lineitem` have attributes of built-in types. The object type `purchase_order` has a more complex structure, which closely matches the structure of real purchase orders.

The attributes of `purchase_order` are `id`, `contact`, and `lineitems`. The attribute `contact` is an object, and the attribute `lineitems` is a nested table (see "Nested Tables" on page 11-11).

    CREATE TYPE external_person AS OBJECT (
      name        VARCHAR2(30),
      phone       VARCHAR2(20) );

    CREATE TYPE lineitem AS OBJECT (
      item_name   VARCHAR2(30),
      quantity    NUMBER,
      unit_price  NUMBER(12,2) );

    CREATE TYPE lineitem_table AS TABLE OF lineitem;

    CREATE TYPE purchase_order AS OBJECT (
      id          NUMBER,
      contact     external_person,
      lineitems   lineitem_table,

      MEMBER FUNCTION
      get_value   RETURN NUMBER );

This is a simplified example. It does not show how to specify the body of the method `get_value`. Nor does it show the full complexity of a real purchase order.

Additional Information: See Oracle8 Application Developer's Guide for a complete purchase order example.

An object type is a template. Defining it doesn't result in storage allocation. You can use `lineitem`, `external_person`, or `purchase_order` 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:

    CREATE TABLE contacts (
      contact     external_person
      date        DATE );

The `contact` table is a relational table with an object type defining one of its columns. Objects that occupy columns of relational tables are called column objects (see "Row Objects and Column Objects" on page 11-8).

#### Methods

In the example, `purchase_order` has a method named get_value. Each purchase order object has its own get_value method. For example, if `x` and `y` are PL/SQL variables that hold purchase order objects and `w` and `z` are variables that hold numbers, the following two statements can leave `w` and `z` with different values:

    w = x.get_value();
    z = y.get_value();

After those statements, `w` has the value of the purchase order referred to by variable `x`; `z` has the value of the purchase order referred to by variable `y`.

The term `x.get_value` () is an invocation of the method `get_value`. Method definitions can include parameters, but `get_value` does not need them, because it finds all of its arguments among the attributes of the object to which its invocation is tied. That is, in the first of the sample statements, it computes its value using the attributes of purchase order `x`. In the second it computes its value using the attributes of purchase order `y`. This is called the selfish style of method invocation.

Every object type also has one implicitly defined method that is not tied to specific objects, the object type's constructor method.

##### Object Type Constructor Methods

Every object type has a system-defined constructor method, that is, a method that makes a new object according to the object type's specification. The name of the constructor method is the name of the object type. Its parameters have the names and types of the object type's attributes. The constructor method is a function. It returns the new object as its value.

For example, the expression

    purchase_order(
      1000376,
      external_person ("John Smith","1-800-555-1212"),
      NULL )

represents a purchase order object with the following attributes:

    id         1000376
    contact    external_person("John Smith","1-800-555-1212")
    lineitems  NULL

The expression `external_person ("John Smith", "1-800-555-1212")` is an invocation of the constructor function for the object type `external_person.` The object that it returns becomes the contact attribute of the purchase order.

See "Nulls" on page 12-6 for a discussion of null objects and null attributes.

##### Comparison Methods

Methods play a role in comparing objects. Oracle has facilities for comparing two data items of a given built-in type (for example, two numbers), and determining whether one is greater than, equal to, or less than the other. Oracle cannot, however, compare two items of an arbitrary user-defined type without further guidance from the definer. Oracle provides two ways to define an order relationship among objects of a given object type: map methods and order methods.

Map methods use Oracle's ability to compare built-in types. Suppose, for example, that you have defined an object type called `rectangle`, with attributes `height` and `width`. You can define a map method area that returns a number, namely the product of the rectangle's `height` and `width` attributes. Oracle can then compare two rectangles by comparing their areas.

Order methods are more general. An order method uses its own internal logic to compare two objects of a given object type. It returns a value that encodes the order relationship. For example, it may return -1 if the first is smaller, 0 if they are equal, and 1 if the first is larger.

Suppose, for example, that you have defined an object type called `address`, with attributes `street`, `city`, `state`, and `zip`. The terms "greater than" and "less than" may have no meaning for addresses in your application, but you may need to perform complex computations to determine when two addresses are equal.

In defining an object type, you can specify either a map method or an order method for it, but not both. If an object type has no comparison method, Oracle cannot determine a greater than or less than relationship between two objects of that type. It can, however, attempt to determine whether two objects of the type are equal.

Oracle compares two objects of a type that lacks a comparison method by comparing corresponding attributes:

- If all the attributes are non-null and equal, Oracle reports that the objects are equal.
- If there is an attribute for which the two objects have unequal non-null values, Oracle reports them unequal.
- Otherwise, Oracle reports that the comparison is not available (null).

  Additional Information: For examples of how to specify and use comparison methods, see Oracle8 Application Developer's Guide.

#### Object Tables

An object table is a special kind of table that holds objects and provides a relational view of the attributes of those objects.

For example, the following statement defines an object table for objects of the `external_person` type defined earlier:

    CREATE TABLE external_person_t OF external_person;

Oracle allows you to view this table in two ways:

- A single column table in which each entry is an `external_person` object.
- A multi-column table in which each of the attributes of the object type `external_person`, namely `name` and `phone`, occupies a column.

For example, you can execute the following instructions:

    INSERT INTO external_person_t VALUES (
           "John Smith",
           "1-800-555-1212" );

    SELECT VALUE(p) FROM external_person_t p
            WHERE p.name = "John Smith";

The first instruction inserts a purchase order object into `external_person_t` as a multi-column table. The second selects from `external_person_t` as a single column table.

##### Row Objects and Column Objects

Objects that appear in object tables are called row objects. Objects that appear only in table columns or as attributes of other objects are called column objects.

#### REFs

In the relational model, foreign keys express many-to-one relationships. Oracle with the Objects option provides a more efficient means of expressing many-to-one relationships when the "one" side of the relationship is a row object. Oracle gives every row object a unique, immutable identifier, called an object identifier. Oracle provides no documentation of or access to the internal structure of object identifiers. This structure can change at any time.

An object identifier allows the corresponding row object to be referred to from other objects or from relational tables. A built-in datatype called REF represents such references. A REF encapsulates a reference to a row object of a specified object type.

An object view (see Chapter 13, "Object Views") is a virtual object table. Its rows are row objects. Oracle materializes object identifiers, which it does not store persistently, from primary keys in the underlying table or view. Oracle uses these identifiers to construct REFs to the row objects in the object view.

You can use a REF to examine or update the object it refers to. You can also use a REF to obtain a copy of the object it refers to. The only changes you can make to a REF are to replace its contents with a reference to a different object of the same object type or to assign it a null value.

##### 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 REFs require less storage space and allow more efficient access than unscoped REFs.

##### Dangling REFs

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

##### 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 results in a null object.

Oracle provides implicit dereferencing of REFs. For example, consider the following:

    CREATE TYPE person AS OBJECT (
      name    VARCHAR2(30),
      manager REF person );

If x represents an object of type `person`, then the expression

    x.manager.name

represents a string containing the `name` attribute of the `person` object referred to by the `manager` attribute of `x`. The above expression is a shortened form of:

    y.name, where y = DEREF(x.manager)

##### Obtaining REFs

You can obtain a REF to a row object by selecting the object from its object table and applying the REF operator. For example, you can obtain a REF to the purchase order with identification number 1000376 as follows:

    DECLARE OrderRef REF to purchase_order;

    SELECT REF(po) INTO OrderRef
                   FROM purchase_order_table po
                   WHERE po.id = 1000376;

For more on storage of objects and REFs, see "Storage of User-Defined Types" on page 12-4.

Additional Information: For examples of how to use REFs, see Oracle8 Application Developer's Guide.

### Collection Types

Each collection type describes a data unit made up of an indefinite number of elements, all of the same datatype. The collection types are array types and table types.

Array types and table types are schema objects. The corresponding data units are called VARRAYs and nested tables. When there is no danger of confusion, we often refer to the collection types as VARRAYs and nested tables.

Collection types have constructor methods. The name of the constructor method is the name of the type, and its argument is a comma-separated list of the new collection's elements. The constructor method is a function. It returns the new collection as its value.

An expression consisting of the type name followed by empty parentheses represents a call to the constructor method to create an empty collection of that type. An empty collection is different from a null.

#### VARRAYs

An array is an ordered set of data elements. All elements of a given array are of the same datatype. Each element has an index, which is a number corresponding to the element's position in the array.

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. You must specify a maximum size when you declare the array type.

For example, the following statement declares an array type:

    CREATE TYPE prices AS VARRAY(10) OF NUMBER(12,2);

The VARRAYs of type `prices` have no more than ten elements, each of datatype NUMBER(12,2).

Creating an array 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
- A PL/SQL variable, parameter, or function return type.

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, however, Oracle stores it as a BLOB (see "Import/Export of User-Defined Types" on page 12-15).

Additional Information: For more information on using VARRAYs, see Oracle8 Application Developer's Guide.

#### Nested Tables

A nested table is an unordered set of data elements, all of the same datatype. It has a single column, and the type of that column is a built-in type or an object type. If an object type, the table can also be viewed as a multi-column table, with a column for each attribute of the object type.

For example, in the purchase order example, the following statement declares the table type used for the nested tables of line items:

    CREATE TYPE lineitem_table AS TABLE OF lineitem;

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 table type appears as the type of a column in a relational table or as an attribute of the underlying object type of an object table, Oracle stores all of the nested table data in a single table, which it associates with the enclosing relational or object table (see "Nested Tables" on page 12-5). For example, the following statement defines an object table for the object type `purchase_order`:

    CREATE TABLE purchase_order_table OF purchase_order
       NESTED TABLE lineitems STORE AS lineitems_table;

The second line specifies `lineitems_table` as the storage table for the `lineitems` attributes of all of the `purchase_order` objects in `purchase_order_table`.

A convenient way to access the elements of a nested table individually is to use a nested cursor.

Additional Information: See Oracle8 Reference for information about nested cursors, and see Oracle8 Application Developer's Guide for more information on using nested tables.

## Application Interfaces

Oracle provides a number of facilities for using user-defined datatypes in application programs:

- SQL
- PL/SQL
- Pro*C/C++
- OCI
- OTT

### SQL

Oracle SQL DDL provides the following support for user-defined datatypes:

- defining object types, nested tables, and arrays
- specifying privileges
- specifying table columns of user-defined types
- creating object tables

Oracle SQL DML provides the following support for user-defined datatypes:

- querying and updating objects and collections
- manipulating REFs

  Additional Information: For a complete description of Oracle SQL syntax, see Oracle8 SQL Reference.

### PL/SQL

PL/SQL is a procedural language that extends SQL. It offers modern software engineering features like packages, data encapsulation, information hiding, overloading, and exception handling. It is the language used for stored procedures.

PL/SQL allows use from within functions and procedures of the SQL features that support user-defined types.

The parameters and variables of PL/SQL functions and procedures can be of user-defined types.

PL/SQL provides all the capabilities necessary to implement the methods associated with object types. These methods (functions and procedures) reside on the server as part of a user's schema.

Additional Information: For a complete description of PL/SQL, see PL/SQL User's Guide and Reference.

### 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.
- A simple interface to the object cache (described under OCI), where objects can be accessed by traversing pointers, then modified and updated on the server.

  Additional Information: For a complete description of the Pro*C precompiler, see Pro*C/C++ Precompiler Programmer's Guide.

### OCI

The Oracle call interface (OCI) is a set of C language interfaces to the Oracle server. It provides programmers great flexibility in using the server's capabilities.

An important component of OCI is a set of calls to allow application programs to use 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 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.

Additional Information: For a complete description of OCI, see Oracle Call Interface Programmer's Guide.

### OTT

The Oracle type translator (OTT) is a program that automatically generates C language structure declarations corresponding to object types. OTT facilitates using the Pro*C precompiler and the OCI server access package.

Additional Information: For complete information about OTT, see Oracle Call Interface Programmer's Guide and Pro*C/C++ Precompiler Programmer's Guide.

Prev | Next
| Copyright © 1997 Oracle Corporation. All Rights Reserved. |
Library | Product | Contents | Index