Oracle Object Based DB Programming Guide
Oracle Object Based DB Programming Guide
June 2005
Oracle Database Application Developer's Guide - Object-Relational Features 10g Release 2 (10.2)
B14260-01
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.
Contents
iii
Indexes for Object Tables .................................................................................................................. 2-4
Triggers for Object Tables ................................................................................................................. 2-4
Rules for REF Columns and Attributes .......................................................................................... 2-5
Name Resolution................................................................................................................................ 2-5
When Table Aliases Are Required ........................................................................................... 2-6
Restriction on Using User-Defined Types with a Remote Database .......................................... 2-7
Object Methods ........................................................................................................................................ 2-7
Member Methods ............................................................................................................................... 2-7
Methods for Comparing Objects...................................................................................................... 2-8
Map Methods............................................................................................................................... 2-9
Order Methods ............................................................................................................................ 2-9
Guidelines for Comparison Methods.................................................................................... 2-10
Comparison Methods in Type Hierarchies .......................................................................... 2-10
Static Methods ................................................................................................................................. 2-11
Constructor Methods...................................................................................................................... 2-11
External Implemented Methods ................................................................................................... 2-11
Inheritance in SQL Object Types ....................................................................................................... 2-12
Types and Subtypes ........................................................................................................................ 2-12
FINAL and NOT FINAL Types and Methods ............................................................................ 2-14
Creating Subtypes With Overriding Methods............................................................................ 2-14
NOT INSTANTIABLE Types and Methods................................................................................ 2-17
Inheriting, Overloading, and Overriding Methods ................................................................... 2-18
Overloading Methods ............................................................................................................. 2-18
Redefining Methods ................................................................................................................ 2-19
Restrictions on Overriding Methods..................................................................................... 2-19
Dynamic Method Dispatch............................................................................................................ 2-20
Substituting Types in a Type Hierarchy ...................................................................................... 2-21
Column and Row Substitutability ................................................................................................ 2-21
Using OBJECT_VALUE and OBJECT_ID with Substitutable Rows ................................ 2-22
Subtypes Having Supertype Attributes................................................................................ 2-22
REF Columns and Attributes ................................................................................................. 2-23
Collection Elements ................................................................................................................. 2-23
Creating Subtypes After Creating Substitutable Columns ....................................................... 2-23
Dropping Subtypes After Creating Substitutable Columns ..................................................... 2-24
Turning Off Substitutability in a New Table .............................................................................. 2-24
Constraining Substitutability ........................................................................................................ 2-25
Modifying Substitutability............................................................................................................. 2-25
Restrictions on Modifying Substitutability ................................................................................. 2-26
Assignments Across Types ............................................................................................................ 2-26
Objects and REFs to Objects ................................................................................................... 2-26
Collection Assignments .......................................................................................................... 2-27
Comparisons of Objects, REF Variables, and Collections ......................................................... 2-28
Comparing Object Instances................................................................................................... 2-28
Comparing REF Variables ...................................................................................................... 2-28
Functions and Operators Useful with Objects ................................................................................ 2-28
CAST ................................................................................................................................................. 2-29
CURSOR ........................................................................................................................................... 2-29
iv
DEREF............................................................................................................................................... 2-29
IS OF type ......................................................................................................................................... 2-29
REF .................................................................................................................................................... 2-31
SYS_TYPEID .................................................................................................................................... 2-31
TABLE() ............................................................................................................................................ 2-32
TREAT............................................................................................................................................... 2-32
VALUE.............................................................................................................................................. 2-33
v
4 Object Support in Oracle Programming Environments
SQL.............................................................................................................................................................. 4-1
PL/SQL........................................................................................................................................................ 4-2
Oracle Call Interface (OCI)..................................................................................................................... 4-2
Associative Access in OCI Programs .............................................................................................. 4-2
Navigational Access in OCI Programs............................................................................................ 4-3
Object Cache........................................................................................................................................ 4-3
Building an OCI Program That Manipulates Objects ................................................................... 4-4
Defining User-Defined Constructors in C ...................................................................................... 4-4
Pro*C/C++ .................................................................................................................................................. 4-5
Associative Access in Pro*C/C++ ................................................................................................... 4-5
Navigational Access in Pro*C/C++ ................................................................................................ 4-5
Converting Between Oracle Types and C Types........................................................................... 4-6
Oracle Type Translator (OTT) .......................................................................................................... 4-6
Oracle C++ Call Interface (OCCI) ......................................................................................................... 4-6
OCCI Associative Relational and Object Interfaces ...................................................................... 4-7
The OCCI Navigational Interface .................................................................................................... 4-7
Oracle Objects For OLE (OO4O) ........................................................................................................... 4-7
Representing Objects in Visual Basic (OraObject)......................................................................... 4-8
Representing REFs in Visual Basic (OraRef) .................................................................................. 4-9
Representing VARRAYs and Nested Tables in Visual Basic (OraCollection) .......................... 4-9
Java: JDBC, Oracle SQLJ, JPublisher, and SQLJ Object Types ....................................................... 4-9
JDBC Access to Oracle Object Data .............................................................................................. 4-10
SQLJ Access to Oracle Object Data ............................................................................................... 4-10
Choosing a Data Mapping Strategy ............................................................................................. 4-10
Using JPublisher to Create Java Classes for JDBC and SQLJ Programs ................................. 4-11
What JPublisher Produces for a User-Defined Object Type .............................................. 4-11
Java Object Storage ......................................................................................................................... 4-12
Representing SQLJ Types to the Server ................................................................................ 4-12
Creating SQLJ Object Types ................................................................................................... 4-13
Additional Notes About Mapping ........................................................................................ 4-13
Evolving SQLJ Types............................................................................................................... 4-14
Constraints ................................................................................................................................ 4-14
Querying SQLJ Objects ........................................................................................................... 4-14
Inserting Java Objects .............................................................................................................. 4-15
Updating SQLJ Objects ........................................................................................................... 4-15
Defining User-Defined Constructors in Java .............................................................................. 4-15
XML.......................................................................................................................................................... 4-15
vi
Multilevel Collections in Object Views ........................................................................................... 5-6
Specifying Object Identifiers for Object Views................................................................................. 5-7
Creating References to View Objects ................................................................................................... 5-7
Modelling Inverse Relationships with Object Views....................................................................... 5-8
Updating Object Views ........................................................................................................................... 5-9
Updating Nested Table Columns in Views.................................................................................... 5-9
Using INSTEAD OF Triggers to Control Mutating and Validation ........................................ 5-10
Applying the Object Model to Remote Tables ................................................................................ 5-10
Defining Complex Relationships in Object Views ........................................................................ 5-11
Tables and Types to Demonstrate Circular View References................................................... 5-12
Creating Object Views with Circular References ....................................................................... 5-13
Object View Hierarchies ...................................................................................................................... 5-14
Creating an Object View Hierarchy.............................................................................................. 5-16
The Flat Model.......................................................................................................................... 5-16
The Horizontal Model ............................................................................................................. 5-18
The Vertical Model .................................................................................................................. 5-19
Querying a View in a Hierarchy ................................................................................................... 5-20
Privileges for Operations on View Hierarchies .......................................................................... 5-21
vii
Leaf-Level Attributes ......................................................................................................................... 7-1
How Row Objects Are Split Across Columns................................................................................ 7-1
Hidden Columns for Tables with Column Objects....................................................................... 7-2
Hidden Columns for Substitutable Columns and Tables ............................................................ 7-2
REFs...................................................................................................................................................... 7-3
Internal Layout of Nested Tables..................................................................................................... 7-3
Internal Layout of VARRAYs........................................................................................................... 7-3
Creating Indexes on Typeids or Attributes ......................................................................................... 7-4
Indexing a Type Discriminant Column .......................................................................................... 7-4
Indexing Subtype Attributes of a Substitutable Column ............................................................. 7-4
Type Evolution .......................................................................................................................................... 7-5
Changes Involved When a Type Is Altered ................................................................................... 7-6
Altering a Type by Adding a Nested Table Attribute .................................................................. 7-7
Validating a Type That Has Been Altered...................................................................................... 7-9
If a Type Change Validation Fails ................................................................................................ 7-11
ALTER TYPE Statement for Type Evolution .............................................................................. 7-12
ALTER TABLE Statement for Type Evolution ........................................................................... 7-14
The Attribute-Value Constructor.................................................................................................. 7-15
Constructors and Type Evolution................................................................................................. 7-15
Advantages of User-Defined Constructors ................................................................................. 7-15
Defining and Implementing User-Defined Constructors ......................................................... 7-15
Overloading and Hiding Constructors ........................................................................................ 7-17
Calling User-Defined Constructors .............................................................................................. 7-17
Constructors for SQLJ Object Types............................................................................................. 7-18
Transient and Generic Types............................................................................................................... 7-19
User-Defined Aggregate Functions ................................................................................................... 7-22
Partitioning Tables That Contain Oracle Objects ........................................................................... 7-22
How Locators Improve the Performance of Nested Tables...................................................... 7-23
viii
Propagating VARRAY Size Change...................................................................................... 8-10
Performance of Varrays Versus Nested Tables .......................................................................... 8-10
Design Considerations for Nested Tables ................................................................................... 8-10
Nested Table Storage............................................................................................................... 8-11
Nested Table Indexes .............................................................................................................. 8-13
Nested Table Locators ............................................................................................................. 8-13
Optimizing Set Membership Queries ................................................................................... 8-14
Design Considerations for Multilevel Collections ..................................................................... 8-15
Design Considerations for Methods ................................................................................................. 8-18
Choosing a Language for Method Functions.............................................................................. 8-18
Static Methods ................................................................................................................................. 8-20
Using SELF IN OUT NOCOPY with Member Procedures ....................................................... 8-21
Function-Based Indexes on the Return Values of Type Methods ............................................ 8-21
Writing Reusable Code Using Invoker Rights ................................................................................ 8-22
Replicating Object Tables and Columns .......................................................................................... 8-23
Replicating Columns of Object, Collection, or REF Type ......................................................... 8-23
Replicating Object Tables............................................................................................................... 8-24
Constraints on Objects ......................................................................................................................... 8-24
Considerations Related to Type Evolution....................................................................................... 8-25
Pushing a Type Change Out to Clients........................................................................................ 8-25
Changing Default Constructors .................................................................................................... 8-25
Altering the FINAL Property of a Type....................................................................................... 8-26
Parallel Queries with Oracle Objects ................................................................................................ 8-26
Design Consideration Tips and Techniques .................................................................................... 8-26
Deciding Whether to Evolve a Type or Create a Subtype Instead........................................... 8-26
How ANYDATA Differs from User-Defined Types.................................................................. 8-27
Polymorphic Views: An Alternative to an Object View Hierarchy ......................................... 8-27
The SQLJ Object Type..................................................................................................................... 8-28
The Intended Use of SQLJ Object Types............................................................................... 8-28
Actions Performed When Creating a SQLJ Object Type.................................................... 8-28
Uses of SQLJ Object Types...................................................................................................... 8-29
Uses of Custom Object Types................................................................................................. 8-29
Differences Between SQLJ and Custom Object Types Through JDBC ............................ 8-29
Miscellaneous Tips.......................................................................................................................... 8-29
Column Substitutability and the Number of Attributes in a Hierarchy.......................... 8-30
Circular Dependencies Among Types .................................................................................. 8-30
ix
Querying Data Under the Relational Model ................................................................................. A-6
Updating Data Under the Relational Model ................................................................................. A-7
Deleting Data Under the Relational Model................................................................................... A-7
Implementing the Schema on the Object-Relational Model.......................................................... A-7
Defining Types .................................................................................................................................. A-8
Method Definitions ......................................................................................................................... A-12
The getPONo Method ............................................................................................................. A-13
The sumLineItems Method..................................................................................................... A-13
The compareCustOrders Method.......................................................................................... A-14
Creating Object Tables.................................................................................................................... A-14
The Object Table Customer_objtab ....................................................................................... A-15
Object Datatypes as a Template for Object Tables ..................................................................... A-16
Object Identifiers and References ................................................................................................. A-16
Object Tables with Embedded Objects ........................................................................................ A-17
The Object Table Stock_objtab ............................................................................................... A-17
The Object Table PurchaseOrder_objtab .............................................................................. A-17
Inserting Values........................................................................................................................ A-22
Querying ................................................................................................................................... A-24
Deleting ..................................................................................................................................... A-25
Evolving Object Types ......................................................................................................................... A-26
Adding an Attribute to the Customer Type................................................................................ A-27
Working with Multilevel Collections........................................................................................... A-29
Inserting into Nested Tables................................................................................................... A-29
Inserting a New Purchase Order with Line Items .............................................................. A-30
Querying Multilevel Nested Tables ...................................................................................... A-31
Type Inheritance and Substitutable Columns............................................................................. A-33
Creating a Subtype................................................................................................................... A-33
Inserting Subtypes ................................................................................................................... A-34
Querying Substitutable Columns .......................................................................................... A-35
Index
x
Send Us Your Comments
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: [email protected]
■ 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.
xi
xii
Preface
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/
xiii
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.
Structure
This document contains:
xiv
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:
■ For additional information on objects, see the Oracle Technology Network (OTN),
at http://www.oracle.com/technology/index.html
If you want to access information for a specific topic on OTN, such as
"object-relational technology", enter the appropriate phrase in the search field on
the OTN main page at http://www.oracle.com/technology/
■ Oracle Database Application Developer's Guide - Large Objects for information on
Large Objects (LOBs)
■ Oracle Database Application Developer's Guide - Fundamentals for general information
about developing applications
■ Oracle Database PL/SQL User's Guide and Reference for information on PL/SQL, the
procedural language extension to Oracle SQL
■ Oracle XML DB Developer's Guide and Oracle XML Developer's Kit Programmer's
Guide for information about developing applications with XML
■ Oracle Database JDBC Developer's Guide and Reference and Oracle Database Java
Developer's Guide to use Oracle object-relational features through Java
■ Oracle Call Interface Programmer's Guide and Oracle C++ Call Interface Programmer's
Guide for information on using the Oracle Call Interface (OCI) and Oracle C++ Call
Interface to build third-generation language (3GL) applications that access the
Oracle Server
■ Pro*C/C++ Programmer's Guide for information on Oracle's Pro* series of
precompilers, which allow you to embed SQL and PL/SQL in 3GL application
programs written in Ada, C, C++, COBOL, or FORTRAN
■ Oracle Database SQL Reference and Oracle Database Administrator's Guide for
information on SQL
■ Oracle Database Concepts for information on basic Oracle concepts
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/
xv
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
■ Conventions in Code Examples
■ Conventions for Windows Operating Systems
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.
xvi
Conventions in Code Examples
Code examples illustrate SQL, PL/SQL, SQL*Plus, or other command-line statements.
They are displayed in a monospace (fixed-width) font and separated from normal text
as shown in this example:
SELECT USERNAME FROM DBA_USERS WHERE USERNAME = 'MIGRATE';
The following table describes typographic conventions used in code examples and
provides examples of their use.
xvii
Conventions for Windows Operating Systems
The following table describes conventions for Windows operating systems and
provides examples of their use.
xviii
Convention Meaning Example
ORACLE_HOME In releases prior to Oracle8i release 8.1.3, Go to the ORACLE_BASE\ORACLE_
and ORACLE_ when you installed Oracle components, all HOME\rdbms\admin directory.
BASE subdirectories were located under a top
level ORACLE_HOME directory that by
default used one of the following names:
■ C:\orant for Windows NT
■ C:\orawin98 for Windows 98
This release complies with Optimal
Flexible Architecture (OFA) guidelines. All
subdirectories are not under a top level
ORACLE_HOME directory. There is a top
level directory called ORACLE_BASE that
by default is C:\oracle. If you install the
latest Oracle release on a computer with no
other Oracle software installed, then the
default setting for the first Oracle home
directory is C:\oracle\orann, where nn
is the latest release number. The Oracle
home directory is located directly under
ORACLE_BASE.
All directory path examples in this guide
follow OFA conventions.
Refer to Oracle Database Platform Guide for
Microsoft Windows (32-Bit) for additional
information about OFA compliances and
for information about installing Oracle
products in non-OFA compliant
directories.
xix
xx
What’s New in Object-Relational Features?
This section describes the new object-relational features of Oracle 10g release 2 (10.2).
New features information from previous releases is also retained to help those users
upgrading to the current release.
The following sections describe the new features in Oracle Object-Relational Features:
■ Oracle Database 10g Release 1 (10.1) New Features in Object-Relational Features
xxi
xxii
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
■ Advantages of Objects
■ Key Features of the Object-Relational Model
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.
Attributes Methods
idno get_idno
first_name display_details
last_name
email
phone
Object Object
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.
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.
spec
attribute declarations
public interface
method specs
body
method bodies private implementation
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 );
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" on page 1-7.
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:
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" on page 2-7.
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" on page 2-12.
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.
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" on page 2-33 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)" on page 8-4
for information on Object Identifiers and using REFs to OIDs.
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.
See "Rules for REF Columns and Attributes" on page 2-5 and "Design Considerations
for REFs" on page 8-6.
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.
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" on page 2-12.
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" on page 2-5.
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.
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.
The query must return exactly one row. See "Storage Size of REFs" on page 8-6.
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.
SQLJ object types where all the methods are implemented in their corresponding Java
classes. See "Java Object Storage" on page 4-12.
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.
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.
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)" on page 4-2.
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
■ Object Methods
■ Inheritance in SQL Object Types
■ Functions and Operators Useful with Objects
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.
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.
For example, the following statement creates an object with both a character-length
VARCHAR2 attribute and an NCHAR attribute:
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.
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.
Wherever Oracle expects a column name in an index definition, you can also specify a
scalar attribute of an object column.
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);
In some cases, object-relational features require you to specify the table aliases.
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
■ Methods for Comparing Objects
■ Static Methods
■ Constructor Methods
■ External Implemented Methods
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.
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" on
page 8-21.
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 on page 2-2 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:
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" on page 3-14 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.
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" on page 2-12 and "Inheriting, Overloading, and Overriding Methods" on
page 2-18.
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" on page 8-20 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 on page 2-2. 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;
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" on page 7-15 for information on user-defined constructors
and their advantages. See "Constructor Methods for Collections" on page 3-1 for
information on user-defined constructors for collections.
See Also: Oracle Database PL/SQL User's Guide and Reference for
information on external implemented methods
A
Supertype of all
B D
Subtype of A; Subtype of A;
supertype of C
C
Subtype of B
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" on page 2-18.
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.
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;
/
END;
/
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.
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.
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.
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.
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.
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.
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;
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" on page 2-14.
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" on
page 2-20.
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;
As with new methods, you supply the declaration for a method that hides or overrides
in a CREATE TYPE BODY statement.
■ 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"
on page 2-14 for the definition of the supertype and subtype functions.
Subtype of
circle_typ ellipse_type
Subtype of
sphere_typ circle_type
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
contact person_typ,
contact_date DATE );
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;
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
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.
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);
/
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);
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;
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:
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:
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.
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;
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;
/
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;
/
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;
/
■ REF
■ SYS_TYPEID
■ TABLE()
■ TREAT
■ VALUE
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:
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.
See "Dereferencing REFs" on page 1-9. 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.
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:
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" on page 7-2 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 on page 2-16.
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:
See "Hidden Columns for Substitutable Columns and Tables" on page 7-2 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;
See "Assignments Across Types" on page 2-26 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.
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" on page 3-13. For
more information about the SQL VALUE function, see Oracle Database SQL Reference.
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
■ Operations on Collection Datatypes
Example 3–1 Using the Constructor Method to Insert Values into a Nested Table
CREATE TYPE people_typ AS TABLE OF person_typ;
/
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;
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.
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" on page 8-9.
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.
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 on page 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" on page 8-11.
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 on page 2-2 and people_typ defined in
Example 3–1 on page 3-1.
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);
/
Example 3–7 shows explicit LOB storage specified for a varray of varray type.
See "Storage Considerations for Varrays" on page 8-9. See also Oracle Database
Application Developer's Guide - Large Objects.
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;
When a VARRAY type is altered, changes are propagated to the dependent tables. See
"Propagating VARRAY Size Change" on page 8-10.
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.
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.
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" on page 8-11.
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.
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.
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.
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;
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" on page 8-8.
Example 3–21 shows VALUE used to return object instance rows for updating:
Collections as Atomic Data Items The section "Constructors for Multilevel Collections" on
page 3-9 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.
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–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.
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 on page 3-4.
In Example 3–25, the nested tables contain person_typ objects which have an
associated map method. See Example 2–1 on page 2-2.
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.
This operator is implemented only for nested tables because this is a multiset function
only.
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.
Set Comparison
The IS [NOT] A SET condition checks whether a given nested table is composed of
unique elements, returning a Boolean value.
Multisets Operations
This section describes multiset operations with nested tables. For a description of
additional operations, see "Comparisons of Objects, REF Variables, and Collections" on
page 2-28. The SQL examples in this section use the nested tables created in
Example 3–4 on page 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.
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" on
page 2-29 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.
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.
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.
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.
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.
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.
For more information about the SET function, see Oracle Database SQL Reference.
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
■ PL/SQL
■ Oracle Call Interface (OCI)
■ Pro*C/C++
■ Oracle C++ Call Interface (OCCI)
■ Oracle Objects For OLE (OO4O)
■ Java: JDBC, Oracle SQLJ, JPublisher, and SQLJ Object Types
■ XML
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
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.
■ 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++" on page 4-5.
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.
See Also: Oracle Call Interface Programmer's Guide for tips and
techniques for using OCI program effectively with objects
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)" on
page 4-2), where objects can be accessed by traversing pointers, then modified and
updated on the server.
■ 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
See Also: For complete information about OTT, see Oracle Call
Interface Programmer's Guide and Pro*C/C++ Programmer's Guide.
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
Figure 4–1 illustrates the containment hierarchy for value instances of all types in
OO4O.
OraObject OraAttribute
OraBLOB
OraCLOB
OraBFILE
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)
Msgbox.Address.City
See Also: Oracle Call Interface Programmer's Guide for tips and
techniques for using OCI program effectively with objects
■ 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/.
See Also: For complete information about JDBC, see the Oracle
Database JDBC Developer's Guide and Reference.
See Also: For complete information about SQLJ, see the Oracle
Database Java Developer's Guide.
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.
See Also: The Oracle Database JPublisher User's Guide for more
information about using JPublisher.
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.
■ 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
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" on page 2-25.
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.
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
■ 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
■ Specifying Object Identifiers for Object Views
■ Creating References to View Objects
■ Modelling Inverse Relationships with Object Views
■ Updating Object Views
■ Applying the Object Model to Remote Tables
■ Defining Complex Relationships in Object Views
■ Object View Hierarchies
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:
■ Oracle Database SQL Reference for a complete description of SQL
syntax and usage.
■ Oracle Database PL/SQL User's Guide and Reference for a
complete discussion of PL/SQL capabilities
■ Oracle Database Java Developer's Guide for a complete discussion
of Java.
■ Oracle Call Interface Programmer's Guide for a complete
discussion of those facilities.
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:
To access the data from the empnum column of the relational table, you would access
the empno attribute of the object type.
See Also: See Oracle Call Interface Programmer's Guide for more
information about OCI calls.
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.
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.
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.
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.
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.
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.
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.
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.
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;
/
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));
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;
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%';
For example, suppose you have the following type hierarchy, with person_typ as the
root:
Person_typ
Student_typ Employee_typ
ParTimeStudent_typ
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.
Table AllPersons
TYPEID Person attributes (columns) Student attributes Employee attributes
1, 2, or 3
View Person_v
Person attributes
View Student_v
View Employee_v
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
The following statements create the views that make up the object view hierarchy:
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.
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" on page 5-20.) Also, indexes on attributes (and unique constraints) must
span multiple tables, and support for this does not currently exist.
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;
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.
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;
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 ONLY(Person_v);
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
■ Dependencies and Incomplete Types
■ Synonyms for Object Types
■ Performance Tuning
■ Tools Providing Support for Objects
■ Utilities Providing Support for Objects
The following statements succeed because USER2 has EXECUTE on USER1's TYPE2
with the GRANT option:
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;
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" on
page 6-2, USER3 can perform the following queries:
SELECT t.col1.attr2 from user2.tab2 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.
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.
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;
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;
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;
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.
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.
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
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.
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.
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.
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
■ Creating Indexes on Typeids or Attributes
■ Type Evolution
■ Transient and Generic Types
■ User-Defined Aggregate Functions
■ Partitioning Tables That Contain Oracle Objects
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.
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.
NAME TYPEID
------------------------------ ---------------------------
Bob Jones 01
Joe Lane 02
Kim Patel 03
column to get the type names corresponding to the typeids in a type discriminant
column. See "SYS_TYPEID" on page 2-31 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.
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));
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).
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" on page 7-12. 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.
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.
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;
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.
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.
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 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" on page 7-11.
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.
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.
T2
Dependent types
Metadata Metadata
2
TB2 TB1
Cascade Including
Table Data
Dependent tables
D2 D1
Other dependent objects
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.
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.
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;
/
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)
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.
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) );
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;
/
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:
■ Oracle Call Interface Programmer's Guide for the OCIType,
OCIAnyData, and OCIAnyDataSet APIs and details on how
to use them.
■ Oracle Database PL/SQL Packages and Types Reference for
information about the interfaces to the ANYTYPE, ANYDATA,
and ANYDATASET types and about the DBMS_TYPES package,
which defines constants for built-in and user-defined types, for
use with ANYTYPE, ANYDATA, and ANYDATASET.
objects in columns of relational tables or object tables. So, address might be a column
object in the customer row object.
See "Design Considerations for Nested Tables" on page 8-10 for more information
about nested tables.
After all of these object types are in place, you can create a table to hold the
information about the people in the organization with the SQL statement in
Example 8–2.
Table PEOPLE_RELTAB
ID NAME_OBJ ADDRESS_OBJ PHONES_NTAB
PK
Text Number
VARCHAR(15) VARCHAR(14)
The people_reltab table has three column objects: name_obj, address_obj, and
phones_ntab. The phones_ntab column object is also a nested table.
The storage for each object stored in the people_reltab table is the same as that of
the attributes of the object. For example, the storage required for a name_obj object is
the same as the storage for the first, middle, and last attributes combined, except
for the null indicator overhead.
If the COMPATIBLE parameter is set to 8.1.0 or higher, the null indicators for an object
and its embedded object attributes occupy one bit each. Thus, an object with n
embedded object attributes (including objects at all levels of nesting) has a storage
overhead of CEIL(n/8) bytes. In the people_reltab table, for example, the
overhead of the null information for each row is one byte because it translates to
CEIL(3/8) or CEIL(.37), which rounds up to one byte. In this case, there are three
objects in each row: name_obj, address_obj, and phones_ntab.
If, however, the COMPATIBLE parameter is set to a value lower than 8.1.0, such as
8.0.0, the storage is determined by the following calculation:
CEIL(n/8) + 6
Here, n is the total number of all attributes (scalar and object) within the object.
Therefore, in the people_reltab table, for example, the overhead of the null
information for each row is seven bytes because it translates to the following
calculation:
CEIL(4/8) + 6 = 7
CEIL(4/8) is CEIL(.5), which rounds up to one byte. In this case, there are three
objects in each row and one scalar.
Therefore, the storage overhead and performance of manipulating a column object is
similar to that of the equivalent set of scalar columns. The storage for collection
attributes are described in the "Viewing Object Data in Relational Form with
Unnesting Queries" section on page 8-8.
However, if an object has a collection of LOB attributes, then Oracle does not compare
the object on a field-by-field basis. Such objects must have a map or order method to
perform comparisons.
you specify a scoped REF to a row object and then delete the row object, the scoped
REF becomes a dangling REF because the referenced object no longer exists.
Unscoped REFs are useful if the application design requires that the objects referenced
be scattered in multiple tables. Because rowid hints are ignored for scoped REFs, you
should use unscoped REFs if the performance gain of the rowid hint, as explained in
the "Speeding up Object Access Using the WITH ROWID Option" on page 8-8,
outweighs the benefits of the storage saving and query optimization of using scoped
REFs.
A people_reltab2 table can be created that has the same definition as the people_
reltab table shown in Example 8–2 on page 8-2, except that a REF is used for the
address. Next, an index can be created on the address_ref column.
The Oracle query optimizer might create a plan to perform a nested-loops join with
address_objtab as the outer table and look up matching addresses using the index
on the address_ref scoped REF column.
If the SELECT list of a query does not refer to any columns from the parent table other
than the nested table column, the query is optimized to execute only against the nested
table's storage table.
The unnesting query syntax is the same for varrays as for nested tables. For instance,
suppose the phones_ntab nested table is instead a varray named phones_var. The
following example shows how to use the TABLE syntax to query the varray:
SELECT p.name_obj, v.num
FROM people_reltab p, TABLE(p.phones_var) v;
RETURN homephones;
END;
/
Now, to query for a list of people and their home phone numbers, enter the following:
To query for a list of people and their home phone numbers, including those people
who do not have a home phone number listed, enter the following:
SELECT p.name_obj, n.num
FROM people_reltab p,
TABLE(CAST(home_phones(p.phones_ntab) AS phone_ntabtyp))(+) n ;
See Also: Oracle Database SQL Reference and Oracle Database Data
Cartridge Developer's Guide for more information about the TABLE
function
size of the varray stored may be slightly greater than the size of the elements
multiplied by the count.
Varrays are stored in columns either as raw values or LOBs. Oracle decides how to
store the varray when the varray is defined, based on the maximum possible size of
the varray computed using the LIMIT of the declared varray. If the size exceeds
approximately 4000 bytes, then the varray is stored in LOBs. Otherwise, the varray is
stored in the column itself as a raw value. In addition, Oracle supports inline LOBs
which means that elements that fit in the first 4000 bytes of a large varray, with some
bytes reserved for the LOB locator, are stored in the column of the row. See also Oracle
Database Application Developer's Guide - Large Objects.
Varray Querying
The unnesting syntax can be used to access varray columns similar to the way it is
used to access nested tables. See "Viewing Object Data in Relational Form with
Unnesting Queries" on page 8-8 for more information.
Varray Updates
Piece-wise updates of a varray value are not supported. Thus, when a varray is
updated, the entire old collection is replaced by the new collection.
Storage Table
NESTED_TABLE_ID Values
B B21
B B22
C C33
A A11
E E51
B B25
E E52
A A12
E E54
B B23
C C32
A A13
D D41
B B24
E E53
Storage Table
NESTED_TABLE_ID Values
Storage for A A11
nested A A12
table A A A13
B B21
Storage for B B22
nested B B23
table B B B24
B B25
Storage for
nested C C31
Storage for table C C C32
nested D D41
table D E E51
Storage for E E52
nested
table E E E53
E E54
In addition, the COMPRESS clause enables prefix compression on the IOT rows. It
factors out the key of the parent in every child row. That is, the parent key is not
repeated in every child row, thus providing significant storage savings.
In other words, if you specify nested table compression using the COMPRESS clause,
the amount of space required for the storage table is reduced because the NESTED_
TABLE_ID is not repeated for each value in a group. Instead, the NESTED_TABLE_ID
is stored only once for each group, as illustrated in Figure 8–4.
Storage Table
NESTED_TABLE_ID Values
Storage for A11
nested A A12
table A A13
B21
Storage for B22
nested B B23
table B B24
B25
Storage for
nested C31
C
Storage for table C C32
nested D D41
table D E51
Storage for E52
nested E
table E E53
E54
In general, Oracle recommends that nested tables be stored in an IOT with the
NESTED_TABLE_ID column as a prefix of the primary key. Further, prefix
compression should be enabled on the IOT. However, if you usually do not retrieve the
nested table as a unit and you do not want to cluster the child rows, do not store the
nested table in an IOT and do not specify compression.
Unlike with the RETURN AS LOCATOR clause, however, you cannot specify a particular
inner collection to return as a locator when using the hint.
Oracle can execute a query that tests the membership in a child-set more efficiently by
transforming it internally into a semijoin. However, this optimization only happens if
the ALWAYS_SEMI_JOIN initialization parameter is set. If you want to perform
semijoins, the valid values for this parameter are MERGE and HASH; these parameter
values indicate which join method to use.
The people_objtab table has the same attributes as the people_reltab table
discussed in "Column Object Storage" on page 8-2. The difference is that the people_
objtab is an object table with row objects, while the people_reltab table is a
relational table with three column objects.
PK
Text Number
VARCHAR(15) VARCHAR(14)
Now you can reference the row objects in the people_objtab object table from other
tables. For example, suppose you want to create a projects_objtab table that
contains:
■ A project identification number for each project.
■ The title of each project.
■ The project lead for each project.
■ A description of each project.
■ Nested table collection of the team of people assigned to each project.
You can use REFs to the people_objtab for the project leads, and you can use a
nested table collection of REFs for the team. To begin, create a nested table object type
called personref_ntabtyp based on the person_objtyp object type:
CREATE TYPE personref_ntabtyp AS TABLE OF REF person_objtyp;
/
Now you are ready to create the object table projects_objtab. First, create the
object type projects_objtyp, then create the object table projects_objtab based
on the projects_objtyp as shown in Example 8–9.
PK
PK
After the people_objtab object table and the projects_objtab object table are in
place, you indirectly have a nested collection. That is, the projects_objtab table
contains a nested table collection of REFs that point to the people in the people_
objtab table, and the people in the people_objtab table have a nested table
collection of phone numbers.
You can insert values into the people_objtab table as shown in Example 8–10.
phone_objtyp('home', '415.642.6722'),
phone_objtyp('work', '650.891.7766'))) ;
Then, you can insert into the projects_objtab relational table by selecting from the
people_objtab object table using a REF operator, as in Example 8–11.
Note: This example uses nested tables to store REFs, but you also
can store REFs in varrays. That is, you can have a varray of REFs.
■ SQL calls
■ Speed of execution
■ Same/different address space
In general, if the application performs intense computations, C is preferable, but if the
application performs a relatively large number of database calls, PL/SQL or Java is
preferable.
A method implemented in C executes in a separate process from the server using
external procedures. In contrast, a method implemented in Java or PL/SQL executes in
the same process as the server.
AS LANGUAGE C
NAME "Crotate"
LIBRARY myCfuncs;
END;
/
See Also:
■ Oracle Database Java Developer's Guide for more information
■ Chapter 4, "Object Support in Oracle Programming
Environments" for more information about choosing a
language
Static Methods
Static methods differ from member methods in that the SELF value is not passed in as
the first parameter. Methods in which the value of SELF is not relevant should be
implemented as static methods. Static methods can be used for user-defined
constructors.
Example 8–13 shows a constructor-like method that constructs an instance of the type
based on the explicit input parameters and inserts the instance into the specified table:.
BEGIN
atype.newa(1, 'atab', 'HR');
END;
/
See Also:
■ Oracle Database PL/SQL User's Guide and Reference for
information on performance issues and restrictions on the use
of NOCOPY
■ Oracle Database SQL Reference for information about using
NOCOPY in the CREATE PROCEDURE statement
SELECT e.name
FROM emps e
WHERE e.bonus() > 2000;
To evaluate this query, Oracle must evaluate bonus() for each row object in the table.
If there is a function-based index on the return values of bonus(), then this work has
already been done, and Oracle can simply look up the results in the index. This
enables Oracle to return a result from the query more quickly.
Return values of a function can be usefully indexed only if those values are constant,
that is, only if the function always returns the same value for each object instance. For
this reason, to use a user-written function in a function-based index, the function must
have been declared with the DETERMINISTIC keyword, as in the preceding example.
This keyword promises that the function always returns the same value for each object
instance's set of input argument values.
The following example creates a function-based index on the method bonus() in the
table emps:
This statement raises an error because the definer of the type (HR) does not have the
privileges required to perform the insert in the newa procedure. You can avoid this
error by defining atype using invoker rights. Here, you first drop the atab table in
both schemas and re-create atype using invoker rights:
DROP TABLE atab;
CONNECT hr/hr;
DROP TABLE atab;
DROP TYPE atype FORCE;
COMMIT;
Now, if user OE tries to use atype again, the statement executes successfully:
GRANT EXECUTE ON atype TO oe;
CONNECT oe/oe;
CREATE TABLE atab OF HR.atype;
BEGIN
HR.atype.newa(1, 'atab', 'OE');
END;
/
DROP TABLE atab;
CONNECT hr/hr;
DROP TYPE atype FORCE;
The statement is successful this time because the procedure is executed under the
privileges of the invoker (OE), not the definer (HR).
In a type hierarchy, a subtype has the same rights model as its immediate supertype.
That is, it implicitly inherits the rights model of the supertype and cannot explicitly
specify one. Furthermore, if the supertype was declared with definer rights, the
subtype must reside in the same schema as the supertype. These rules allow
invoker-rights type hierarchies to span schemas. However, type hierarchies that use a
definer-rights model must reside within a single schema. For example:
CREATE TYPE deftype1 AS OBJECT (...); --Definer-rights type
CREATE TYPE subtype1 UNDER deftype1 (...); --subtype in same schema as supertype
CREATE TYPE schema2.subtype2 UNDER deftype1 (...); --ERROR
CREATE TYPE invtype1 AUTHID CURRENT_USER AS OBJECT (...); --Invoker-rights type
CREATE TYPE schema2.subtype2 UNDER invtype1 (...); --LEGAL
The view-definition query can also select columns of collection or REF type. REFs can
be either primary-key based or have a system-generated key, and they can be either
scoped or unscoped. Scoped REF columns can be rescoped to a different table at the
site of the materialized view—for example, to a local materialized view of the master
table instead of the original, remote table.
As with an ordinary object table, each row of an object materialized view is an object
instance, so the view-definition query that creates the materialized view must select
entire objects from the master table: the query cannot select only a subset of the object
type's attributes. For example, the following materialized view is not allowed:
CREATE MATERIALIZED VIEW customer OF cust_objtyp AS
SELECT CustNo FROM HR.Customer_objtab@dbs1;
You can create an object-relational materialized view from an object table by omitting
the OF type keyword, but such a view is read-only: you cannot create an updatable
object-relational materialized view from an object table.
For example, the following CREATE MATERIALIZED VIEW statement creates a
read-only object-relational materialized view of an object table. Even though the
view-definition query selects all columns and attributes of the object type, it does not
select them as attributes of an object, so the view created is object-relational and
read-only:
CREATE MATERIALIZED VIEW customer AS
SELECT * FROM HR.Customer_objtab@dbs1;
For both object-relational and object materialized views that are based on an object
table, if the type of the master object table is not FINAL, the FROM clause in the
materialized view definition query must include the ONLY keyword. For example:
CREATE MATERIALIZED VIEW customer OF cust_objtyp AS
SELECT CustNo FROM ONLY HR.Customer_objtab@dbs1;
Constraints on Objects
Oracle does not support constraints and defaults in type specifications. However, you
can specify the constraints and defaults when creating the tables:
/
CREATE TYPE department_typ AS OBJECT(
deptno INTEGER);
/
CREATE TABLE customer_tab OF customer_typ (
cust_id default 1 NOT NULL);
where:
■ rel is a release string that is chosen by the product, such as, 'Release 10.1'
■ errmsg is any error message that may need to be returned
■ The function returns 0 on success and a nonzero value on error
You can avoid having to modify constructor calls if you define your own constructor
functions instead of using the system-defined default ones. See "Advantages of
User-Defined Constructors" on page 7-15.
We later find that we need to extend the address type by adding a Country attribute
to support addresses internationally. Is it better to create a subtype of address or to
evolve the address type itself?
With a general base type that has been widely used throughout an application, it is
better to implement the change using type evolution.
Adding Specialization
Suppose that an existing type hierarchy of Graphic types (for example, curve, circle,
square, text) needs to accommodate an additional variation, namely, Bezier curve. To
support a new specialization of this sort that does not reflect a shortcoming of the base
type, we should use inheritance and create a new subtype BezierCurve under the
Curve type.
To sum up, the semantics of the required change dictates whether we should use type
evolution or inheritance. For a change that is more general and affects the base type,
use type evolution. For a more specialized change, implement the change using
inheritance.
creates a view based on queries that select persons from a persons table and
employees from an employees table.
CREATE VIEW Persons_view OF Person_t AS
SELECT Person_t(...) FROM persons
UNION ALL
SELECT TREAT(Employee_t(...) AS Person_t) FROM employees;
An INSTEAD OF trigger defined for this view can use the VALUE function to access the
current object and to take appropriate action based on the object's most specific type.
Polymorphic views and object view hierarchies have these important differences:
■ Addressability: In a view hierarchy, each subview can be referenced
independently in queries and DML statements. Thus, every set of objects of a
particular type has a logical name. However, a polymorphic view is a single view,
so you must use predicates to obtain the set of objects of a particular type.
■ Evolution: If a new subtype is added, a subview can be added to a view hierarchy
without changing existing view definitions. With a polymorphic view, the single
view definition must be modified by adding another UNION branch.
■ DML Statements: In a view hierarchy, each subview can be either inherently
updatable or can have its own INSTEAD OF trigger. With a polymorphic view,
only one INSTEAD OF trigger can be defined for a given operation on the view.
Miscellaneous Tips
This section discusses miscellaneous tips.
See Also:
■ Oracle Database SQL Reference for a complete description of SQL
syntax and usage for user-defined types
■ Oracle Database PL/SQL User's Guide and Reference for a
complete discussion of PL/SQL capabilities
■ Oracle Database Java Developer's Guide for a complete discussion
of Java
■ Oracle Call Interface Programmer's Guide
■ Pro*C/C++ Programmer's Guide
Customer
1
customer number
customer name
street
city
zip
phone1
places
phone2
purchase order number
phone3
N customer number
order date
Purchase Order
ship date
1 tostreet
tocity
tostate
contains
tozip
Line Items
refers
to
Stock Item
stocknumber
price
tax rate
The relational approach results in the tables describe in the following sections.
Customer_reltab
The Customer_reltab table has the following definition:
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:
Stock_reltab
The Stock_reltab table has the following definition:
LineItems_reltab
The LineItems_reltab table has the following definition:
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–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;
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;
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;
places
Zip
1
*
Purchase Order
PONo
OrderDate ShipTo
ShipDate *
getPONo()
sumLineItems()
1
contains
*
Line Item refers to Stock Item
LineItemNo StockNo
1 1 Price
TaxRate
Defining Types
You create an object type with a CREATE TYPE statement. For example, the following
statement creates the type StockItem_objtyp:
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:
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:
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:
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.
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:
■ Chapter 2, "Basic Components of Oracle Objects" for more
information about map and order methods
■ Oracle Database PL/SQL User's Guide and Reference for details
about how to use pragma declarations
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:
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:
MEMBER FUNCTION
sumLineItems RETURN NUMBER
);
/
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:
BEGIN
RETURN PONo;
END;
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;
/
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.
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.
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" on page A-10 and
Example A–17, "Creating the PhoneList_vartyp Type" on page A-10 for the definitions
of those types.
PK
Number
NUMBER
PK
the default 16 byte system-generated identifier. For our example, the primary key is
used as the row object identifier.
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.
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" on page A-10 and
Example A–20, "Creating the LineItemList_ntabtyp Type" on page A-11 for the
definitions of those types.
PK FK
Reference
to a row of
the table
PK
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.
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" on page A-12. 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:
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 + 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.
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:
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.
Refers to a row
of the table
PK
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.
PK FK
Column Object
of the defined type
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.
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.
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:
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:
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–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 on page A-4. 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.
Customer
1
N Purchase Order
1
N Line Item
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.
Now we can use an ALTER TYPE statement to add an attribute of this type to
Customer_objtyp:
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;
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:
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:
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.
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.
); /* 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.
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:
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:
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;
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.
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" on page 7-5.
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.
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:
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:
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:
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.
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:
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:
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:
--------------------------------- ---------------------
Jean Nance CUSTOMER_OBJTYP
John Nike CUSTOMER_OBJTYP
William Kidd CUSTOMER_OBJTYP
Edward Teach CORP_CUSTOMER_OBJTYP
Index-1
SCOPE FOR constraint, A-21 implicit, 1-9, A-13
constructor methods, 1-5, 1-6, 2-11, 7-2 dot notation
literal invocation of, 2-11 using with methods, 2-8
constructors DROP ANY TYPE privilege, 6-1
attribute values, 7-15 See also privileges
calling user-defined, 7-17 DROP TYPE statement, 6-6
methods, 2-11 dump files
overloading, 7-16 Export and Import, 6-11
overriding, 7-16 dynamic method dispatch, 2-20
system defined, 7-15
type evolution, 7-15
E
user-defined, 7-15
with NEW keyword, 7-15 equal and not equal conditions
COUNT attribute of collection types, A-13 nested tables, 3-14
CREATE ANY TYPE privilege, 6-1 evolution
See also privileges object types, 1-6
CREATE INDEX statement Excel, 4-7
object types, 2-4 EXECUTE ANY TYPE privilege, 6-1, 6-2
CREATE TABLE statement See also privileges
column object example, 1-5 EXECUTE privilege
object table example, 1-6 object types, 6-2
object table examples, 2-3 See also privileges
CREATE TRIGGER statement Export utility
object table example, 2-4 object types, 6-11
CREATE TYPE privilege, 6-1 EXTERNAL NAME phrase, 4-12
See also privileges
CREATE TYPE statement, 8-29 F
collection types, 1-10
dependent types, 6-4 features
example, 3-3 new, xxi
nested tables, 3-3 files
object types, 1-3, 1-5, A-8 Export and Import dump file, 6-11
varrays, 3-2, A-10 FINAL keyword, 2-14
creating object types, 1-3 modifying finality, 7-10, 8-26
creating VARRAYs FORCE keyword, 5-13
containing references to LOBs, 3-6 FORCE option, 6-6
CURSOR expression, 2-29 foreign keys
representing many-to-one entity relationship
with, A-5
D function-based indexes
dangling REFs, 1-9 on type methods, 8-21
database administrators (DBAs)
DBA role, 6-1 G
database links
and object types, 2-7 GRANT option for EXECUTE privilege, 6-2
datatypes granting
array types, 3-2 execute object type, 6-2
nested tables, 3-3 guidelines
See also object types comparison methods, 2-10
transient and generic, 7-19
DBA role I
user-defined types, 6-1
implicit dereferencing, 1-9, A-13
DEFAULT clause, 3-2
Import utility
default values
object types, 6-11
collections, 3-2
IN condition, 3-14
object types, 3-2
incomplete object types, 6-5
DELETE privilege
indexes
for object tables, 6-3, 6-4
nested table, 3-4
DEREF function, 2-29
object types, 2-4
dereferencing, 1-9, A-13
on REFs, 2-4
Index-2
type-discriminant column, 7-4 member methods, 1-5, 2-7
index-organized tables member procedures
storing nested tables as, 3-8, 8-11 with SELF IN OUT NOCOPY, 8-21
inheritance, 1-6 methods, A-12
See type inheritance choosing a language for, 8-18
inheriting methods, 2-18 comparison, A-12, A-24
inner capture, 2-6 comparison methods, 2-8
INSERT privilege in a type hierarchy, 2-10
for object tables, 6-3, 6-4 constructor, 1-6
instances constructor methods, 7-2
object type, 1-3 literal invocation, 2-11
objects, 1-5 constructors, 1-5, 2-11
INSTANTIABLE keyword dot notation, 2-8
CREATE TYPE, 2-17 dropping, 7-10
modifying instantiability, 7-10 dynamic method dispatch, 2-20
INSTEAD OF triggers execution privilege for, 6-2
nested tables, 5-9 final, 2-14
invoker-rights function-based indexes, 8-21
object types, 8-22 guidelines for comparison, 2-10
IS A SET condition, 3-15 inheriting, 2-18
IS EMPTY condition, 3-15 instantiability, 2-17
IS NOT A SET condition, 3-15 invoking, 2-8
IS OF type predicate, 2-29 map, 2-9, 8-5, A-11, A-24
map for comparing objects, 2-9
map required for collections, 3-14
J
member, 1-5, 2-7
Java object types, 1-5, 2-7
object storage, 4-12 of object types, 1-4
Oracle JDBC and Oracle objects, 4-10 order, 2-9, 8-5, A-11, A-14
Oracle SQLJ and Oracle objects, 4-10 overloading, 2-14, 2-18
with Oracle objects, 4-9 overriding, 2-14, 2-18, 2-19
JDBC PL/SQL, 4-2
See Oracle JDBC redefining, 2-19
JPublisher, 4-11 restrictions on overriding, 2-19
SELF parameter, 2-7
K static, 1-5, 2-11, 8-20
multilevel collections
keys See collections, multilevel
foreign keys, A-5 MULTISET EXCEPT operator, 3-16
MULTISET INTERSECT operator, 3-16
L multiset operations
with nested tables, 3-15
leaf-level attributes, 7-1
MULTISET UNION operator, 3-17
scalar, 7-1
literal invocation
constructor methods, 2-11 N
locators name resolution
returning nested tables as, 7-23, 8-13, 8-14, A-20 object types, 2-5
using a hint, 8-14 narrowing, 2-27, 2-32
locks nested cursor, A-25
object level locking, 4-2 nested tables, 3-3, 8-10
adding to an object, 7-7
M COMPRESS clause, 8-12
creating, 3-1
managing
creating indexes on, 8-13
object types, 6-1
equal and not equal conditions, 3-14
map methods, 8-5, A-11, A-24
in an index-organized table, 3-8, 8-11
comparing collections, 3-14
indexes, 2-4, 3-4
for comparing objects, 2-9
INSTEAD OF triggers, 5-9
materialized views, 8-24
multiset operations, 3-15
MEMBER condition, 3-15
Index-3
querying, 3-10, A-11 variable arrays (VARRAYs), 3-2
unnesting results, 3-10 column objects, 1-7
returning as locators, 8-13, 8-14, A-20 column objects versus row objects, 8-1
specifying a storage name, 7-7 comparing, 2-28
specifying storage in a tablespace, 3-4 comparison methods for, 2-8, A-12, A-24
storage, 3-7, 8-11, A-19 constructor methods, 1-6
uniqueness in, A-19 constructor methods for, 2-11, 7-2
updating in views, 5-9 creating, 1-3, 1-5
versus VARRAY, A-11 creating subtypes of, 2-15
versus varrays, A-10 database key features, 1-3
NESTED_TABLE_GET_REFS hint, 8-14 dependencies, 6-4
NESTED_TABLE_ID keyword, 3-8, 8-13, A-19 dependents, 6-4, 7-5
NLS_LENGTH_SEMANTICS initialization evolution, 1-6
parameter, 2-3 evolving, 7-5, 8-26
NOCOPY compiler hint design considerations, 8-25
methods, 2-8 SQLJ types, 4-14
performance issues, 8-21 example of privileges, 6-2
use with member procedures, 8-21 Export and Import, 6-11
use with SELF, 2-8, 8-21 final, 8-26
NOT FINAL keyword, 2-14 FINAL or NOT FINAL, 2-14
NOT MEMBER condition, 3-15 in columns, 5-3
nulls incomplete, 6-5
atomic, 2-1 incomplete types, 6-4
object types, 2-1 indexes on column objects, 2-4
indexing, 7-4
inheritance, 1-6, 2-12
O
instances, 1-3
object cache instantiable, 2-17
object views, 5-3 invoker-rights, 8-22
OCI, 4-2 key features, 1-2
privileges, 6-4 locking in cache, 4-2
Pro*C, 4-5 managing, 6-1
object identifiers, 1-7, 8-4, A-16 methods, 2-7
column and index, 8-4 methods in PL/SQL, 4-2
for object types, 7-2 methods of, 1-4, A-12
primary-key based, 8-5 mutually dependent, 6-4
REFs, 8-4 name resolution, 2-5
storage, 8-4 nested tables, 3-3
object instances, 1-3, 1-5 not final, 8-26
comparing, 2-28 not instantiable, 2-17
object tables, 1-6, 8-4, A-14 nulls, 2-1
constraints, 2-3 object references, 5-7
deleting values, A-25 Oracle type translator, 4-6
indexes, 2-4 performance tuning, 6-9
inserting values, A-22 privileges, 6-1
querying, A-24 recompiling, 6-6
replicating, 8-23 remote access to, 2-7, 5-10
row objects, 1-7 row objects, 1-7
triggers, 2-4 row objects and object identifiers, 5-5
virtual object tables, 5-1 schema privileges, 6-1
object types, 1-1 See also type inheritance
adding a nested table attribute, 7-7 specializing, 1-6
advantages, 1-1 SQLJ types, 4-12
altering a type, 7-7 storage, 7-1
assignments across, 2-26 substituting, 2-21
attributes of, 1-4 subtypes, 2-12
character length semantics, 2-2 synonyms, 6-7
collection objects, 5-5 table aliases, 2-6
collections, 3-1 tools, 6-10
nested tables, 3-3 triggers, 2-4
Index-4
use of table aliases, 2-6 OraCollection interface, 4-9
utilities, 6-11 ORAData interface, 4-13
variable arrays (VARRAYs), 3-2 OraObject interface, 4-8
views, 1-7 OraRef interface, 4-9
object views, 1-7, 5-1 order methods, 2-9, 8-5, A-11, A-14
advantages of, 5-1 OTT, 4-6
circular references, 5-12 overloading
defining, 5-2 methods, 2-14, 2-18
hierarchies, 5-14, 8-27 user-defined constructors, 7-16
privileges, 5-21 overloading methods, 2-18
querying in, 5-20 overriding
modeling relationships, 5-8, 5-11 methods, 2-14
multilevel collections in, 5-6 user-defined constructors, 7-16
nested tables, 5-9 overriding methods, 2-18
null objects in, 5-4
OIDs with, 5-7
P
REFs to, 5-7
replicating, 8-23 parallel query
updating through INSTEAD OF triggers, 5-9 objects, 8-26
OBJECT_ID pseudocolumn, 2-22 restrictions for Oracle objects, 8-26
OBJECT_VALUE pseudocolumn, 2-22 view objects, 8-26
object-relational model, A-1 partitioning
advantages, 1-1 tables containing Oracle objects, 7-22
comparing objects, 8-5 pkREFs, 7-3
constraints, 8-24 PL/SQL
database key features, 1-3 bind variables
design considerations, 8-1 object types, 4-2
embedded objects, A-17 object views, 5-3
key features, 1-2 using with objects, 1-7
methods, 1-5, 2-7 polymorphism, 2-12, 8-27
partitioning, 7-22 See also substitutability
programmatic environments for, 4-1, 4-9 POWERMULTISET function, 3-17
replication, 8-23 POWERMULTISET_BY_CARDINALITY
OCCI, 4-6 function, 3-18
OCI pragma RESTRICT_REFERENCES, A-12
associative access, 4-2 primary-key-based REFs, 7-3
for Oracle objects privileges
building a program, 4-4 acquired by role on object types, 6-1
navigational access, 4-3 ALTER ANY TYPE on object types, 6-1
object cache, 4-3 checked when pinning object types, 6-4
OCIObjectFlush, 5-3 column level for object tables, 6-4
OCIObjectPin, 5-3 CREATE ANY TYPE on object types, 6-1
OIDs, 1-7 DELETE on object types, 6-3
See object identifiers DROP ANY TYPE on object types, 6-1
Oracle C++ Call Interface, 4-6 EXECUTE ANY TYPE on object types, 6-1, 6-2
Oracle JDBC EXECUTE ANY TYPE on object types with
accessing Oracle object data, 4-10 ADMIN OPTION, 6-2
Oracle objects EXECUTE on object types, 6-2
See object-relational model EXECUTE on object types with GRANT
Oracle Objects for OLE option, 6-2
OraCollection interface, 4-9 INSERT on object types, 6-3
OraObject interface, 4-8 object types in types or tables, 6-2
OraRef interface, 4-9 object types with CREATE TYPE, 6-1
support of object-relational features, 4-7 object types with DELETE, 6-4
Oracle SQLJ object types with INSERT, 6-4
creating custom Java classes, 4-11 object types with SELECT, 6-4
data mapping for Oracle objects, 4-10 object types with UPDATE, 6-4
JPublisher, 4-11 on object types, 6-1
support for Oracle objects, 4-10 SELECT on object types, 6-3
Oracle type translator (OTT), 4-6 system on object types, 6-1
Index-5
UNDER ANY TYPE on object types, 6-1 S
UNDER ANY VIEW on object types, 6-1
UPDATE on object types, 6-3 schemas
Pro*C object datatypes, 4-2
embedded SQL with user-defined datatypes, 4-5 object types, 1-4
object cache, 4-5 qualifying column names, 2-6
Pro*C/C++ SCOPE FOR constraint, A-21
associative access, 4-5 scoped REFs, 1-8, 7-3
converting between Oracle and C types, 4-6 SELECT privilege
navigational access, 4-5 for object tables, 6-3, 6-4
user-defined datatypes, 4-2 SELF parameter
programmatic environments methods, 2-7
for Oracle objects, 4-1, 4-9 SET function, 3-18
SQL
support for object types, 4-1
Q user-defined datatypes, 4-1
queries OCI, 4-2
set membership, 8-14 SQLData interface, 4-13
unnesting, 8-8 SQLJ
varrays, 8-10 See Oracle SQL
SQLJ object types, 4-9, 8-28
creating, 4-13
R mapping Java classes, 4-13
recompilation See also object types, Oracle SQLJ
object types, 6-6 static methods, 1-5, 2-11
redefining storage
methods, 2-19 column objects, 8-2
REF attributes, 2-5 nested tables, 7-3
REF columns, 2-5 object tables, 7-1
REF function, 2-31 REFs, 7-3
references, 1-8 STORE AS clause, A-19
references See REFs SUBMULTISET condition, 3-14
REFs, 1-8 substitutability, 2-21
comparing, 2-28 attributes, 2-21
constraints on, 2-5, 8-6 collections, 2-21
constructing from object identifiers, 7-2, A-23 column and row, 2-21, 7-4
dangling, 1-9, 2-5 constraining, 2-25
dereferencing of, 1-9, A-13 dependencies, 6-6
for rows of object views, 5-2 modifying, 2-25
implicit dereferencing of, 1-9, A-13 narrowing, 2-27
indexes on, 2-4 OBJECT_ID, 2-22
indexing, 8-7 OBJECT_VALUE, 2-22
object identifiers restrictions on modifying, 2-26
obtaining, 1-9 turning off, 2-24
pinning, 5-3, 6-4 views, 2-21
scoped, 1-8, 2-5, 7-3, 8-6 views and, 8-27
size of, 7-3 widening, 2-26
storage, 8-6 substitutable columns
substitutability, 2-21, 2-23 dropping subtypes, 2-24
use of table aliases, 2-6 subtypes
WITH ROWID option, 8-8 creating, 2-14
remote databases dropping in substitutable columns, 2-24
using with object types, 2-7 hierarchy, 2-12
RESOURCE role indexing attributes of, 7-4
user-defined types, 6-1, 6-2 object types, 2-12
roles specializing, 8-26
DBA role, 6-1 with supertype attribute, 2-22
RESOURCE role, 6-1, 6-2 supertypes
row objects, 1-7 attribute of subtype, 2-22
storage, 8-4 base in hierarchy, 2-12
synonyms
Index-6
object types, 6-7 updates
SYS_TYPEID function, 2-31, 7-4 object views, 5-9
SYS.ANYDATA, 7-19 user-defined aggregate functions, 7-22
SYS.ANYDATASET, 7-19 user-defined constructors, 7-15
SYS.ANYTYPE, 7-19 user-defined datatypes
system privileges See also user-defined types
ADMIN OPTION, 6-2 See object types
object types, 6-1 user-defined types
See also privileges and remote databases, 2-7
See also object-relational model
See object types
T
USING clause, 4-12
TABLE
function, 2-32
TABLE expressions, 3-10, 8-8
V
tables validation
aliases, 2-6 failure, 7-11
constraints on object tables, 2-3 object types, 7-9
functions, 2-32 VALUE function, 2-33
indexes on nested tables, 2-4 variables
indexes on object tables, 2-4 bind variables
nested tables, 3-3 object types, 4-2
object object variables, 5-3
See object tables varrays, 3-2
object tables, 1-6 accessing, 8-10
virtual, 5-1 creating, 3-1
qualifying column names, 2-5, 2-6 creating VARRAYs, 3-6
triggers on object tables, 2-4 increasing the number of elements, 3-6
TREAT function, 2-22, 2-27, 2-30, 2-32, 7-4 querying, 8-10
triggers See also arrays, collections
INSTEAD OF triggers storage, 3-5, 8-9
object views and, 5-9 updating, 8-10
object types, 2-4 versus nested tables, A-10, A-11
type dependencies, 6-6 views
type evolution object, 1-7
See object types See also object views
type hierarchies, 1-6, 2-12 substitutability, 2-21
methods in, 2-10 updatability, 5-9
type inheritance Visual Basic, 4-7
finality, 2-14
instantiability, 2-17
W
methods, 2-18
object types, 2-12 widening
See inheritance and substitutability, 2-26
specializing subtypes, 2-12
typeids, 2-31, 7-4
types
See datatypes, object types
U
UNDER ANY TYPE privilege, 6-1
See also privileges
UNDER ANY VIEW privilege, 6-1
See also privileges
UNDER keyword
CREATE TYPE, 2-14
unnesting queries, 8-8
UPDATE privilege
for object tables, 6-3, 6-4
Index-7
Index-8