Taking Advantage of Oracle8i and the Object Layer, Today!

Joseph R. Hudicka, Dulcian, Inc.

 

Overview

Oracle8i has brought the relational database world into the object-relational arena. The new features of the product make it possible to combine the newer object-oriented structures with the traditional relational constructs. What advantages does the object-relational paradigm have that simple relational databases do not?

Since object-relational databases are very new, some questions arise:

  1. Who is creating object-relational systems? Hardly anyone. ORDBMS’s (Object Relational Database Management Systems) will most likely be rolled out by OO (Object Oriented) shops that are pursuing Oracle as a secure data management environment. These shops tend to use C++, Java or development tools that are based on those languages, and seek technology that can easily implement OO designs.
  2. What is the target market for object relational databases? It is not the RDBMS market since Oracle already owns that portion of the business environment. Users will be forced to choose between Oracle and Microsoft. Today, Oracle and Microsoft can peacefully coexist in most environments. However, while Microsoft is beefing up SQLServer, intending to position it against the Oracle Server, Oracle has incorporated file management into the database as of Oracle8i so that the database is now a complete information management server. It is only a matter of time before Oracle releases an operating system-independent version of the database. This functionality coupled with thin client technology could eliminate the need for operating systems altogether.

This paper will discuss the new features of Oracle 8i, how to use them, whether they are truly object oriented and what the future expectations might be for this product.

 

New Features

There are a number of new features in Oracle8i that require us to rethink some of the traditional methods of designing and building systems.,

 

Object Identifiers (OIDs)

OIDs have been included in Oracle8 to bridge the gap between relational databases and C++/Java development environments. They can serve as pointers for C++ and Java applications. OIDs might sound very similar to Primary and/or Unique Keys. They can be system-generated or based upon a user-defined column. System generated OID’s are encoded values, the contents of which are of absolutely no use by themselves. However, keep in mind that while their values are guaranteed to be unique when they are system-generated, the database cannot guarantee the uniqueness of values from OIDs based upon user-defined columns. Oracle8i includes a new integrity constraint that prevents orphaning in OIDs.

For purely relational database development (including SQL, PL/SQL, Forms and Reports), ROWIDS are still the fastest path to locating specific rows in the database.

OIDs can improve performance in the following ways

SELECT E.ENAME, E.DEPT.DNAME

FROM EMP_TAB E

WHERE E.DEPT.DEPTNO= ‘0100’

WHERE E.DEPT.DEPTNO= ‘0100’

The primary benefit of OID’s within the database world is the way they have greatly simplified the text of some queries as in the following example:

CREATE OR REPLACE TYPE DEPT_TYPE AS OBJECT(

DEPTNO NUMBER(2),

DNAME VARCHAR2(14),

LOC VARCHAR2(13))

/

CREATE OR REPLACE TYPE EMP_TYPE AS OBJECT(

EMPNO NUMBER(4),

ENAME VARCHAR2(10),

JOB VARCHAR2(9),

MGR NUMBER(4),

HIREDATE DATE,

SAL NUMBER(7,2),

COMM NUMBER(7,2),

DEPT REF DEPT_TYPE)

/

CREATE TABLE DEPT_TAB OF DEPT_TYPE(

DEPTNO NOT NULL PRIMARY KEY,

DNAME NOT NULL)

/

CREATE TABLE EMP_TAB OF EMP_TYPE(

EMPNO NOT NULL PRIMARY KEY,

ENAME NOT NULL,

SCOPE FOR (DEPT) IS DEPT_TAB)

/

SELECT E.ENAME, E.DEPT.DNAME

FROM EMP_TAB E

/

 

Types

Types are physical structures that serve as templates or building blocks for other types and/or tables. Whereas Oracle Designer uses the term "Domains," ODD uses "Value Types," and the Oracle8 Server simply calls them "Types." Keep in mind that the physical implementation of an object type can serve multiple functions. .Single column, user-defined Data Types are referenced by their name, eliminating the need to provide an intuitive name to the member placeholders within the Data Types. There are several kinds of user defined types (UDTs). Some sample code for each type is shown below:

  1. Column types: These have no OID. The code for a single column is shown below:

    CREATE OR REPLACE TYPE NAME_T AS OBJECT (

    COL VARCHAR2 (30))

    /

  2. Multi-Column:

    CREATE OR REPLACE TYPE ADDR_T AS OBJECT (

    ADDR1 VARCHAR2 (50),

    ADDR2 VARCHAR2 (50),

    CITY VARCHAR2 (30),

    STATE VARCHAR2 (2),

    ZIP_4 VARCHAR2(9))

    /

  3. Row Types: These include OIDs and form the foundation of object tables/views:

There are some disadvantages to using Types. Types do not support any of the following:

Methods

Methods are another new feature of Oracle 8i. Object-relational databases include the notion of a "class." For ER modelers, simply think of a class as being synonymous with an entity. However, there is one significant difference, namely that classes are associated with "methods." Methods can be thought of as PL/SQL, Java, or C/C++ functions and procedures that act on the class. If you think about classes translating into tables, methods are PL/SQL, Java (Oracle 8i), or C/C++ functions that interact with the tables. For example, for an Employee class, the associated methods might include Hire, Fire, Give Raise, Assign to Dept., and Assign to Committee.

Oracle8i includes four types of methods:

Each will be discussed separately.

Constructor Methods

Constructor methods are automatically created for object classes based upon their object type. This type of method is used to create new objects for the given object class. The constructor method assumes the name of the object type that it is based upon. You do not have to reference the constructor method explicitly in DML statements for row types. Today, the only method type intended for DML operations is the constructor method, which is automatically created for us in direct 1-to-1 correspondence with the Type, itself. However, a future release of Oracle8 will provide the ability for user-defined constructor methods. These user defined constructor methods will not perform DML directly on rows of a table. Rather, they will construct the row to be transacted, and pass that to the parser. An example of a constructor method is shown in the code below:

CREATE OR REPLACE TYPE EMP_T

AS OBJECT (

EMP_ID NUMBER (10),

NAME_TX VARCHAR2(50))

/

CREATE TABLE EMP OF EMP_T

/

INSERT INTO EMP(EMP_ID,NAME_TX)

VALUES(13495,'JOHN SMITH')

/

The automatic generation of constructor methods opens the door to data manipulation as defined by the developer. True object-oriented development would eliminate constructor methods and require manual design and development of an encapsulated set of member methods that define the available data manipulation access paths.

Map and Order Methods

Map and Order methods are used to compare and/or sort data of the same object type. You must, in fact, define either a map or order method within your object type specification in order to perform non-equality comparisons.

Map methods are called once per object and take advantage of both scalar value comparison and kernel implemented functions as opposed to user defined functions.

Order methods require more complicated syntax to accomplish the same task. They require more overhead and must be called for every two objects (rows) being compared.

Sample code for using a map method is shown below:

CREATE OR REPLACE TYPE EMP_T

AS OBJECT (

EMP_ID NUMBER (10),

LNAME_TX VARCHAR2(10),

FNAME_TX VARCHAR2(10),

MAP MEMBER FUNCTION

EMP_MAP RETURN VARCHAR2,

PRAGMA RESTRICT_REFERENCES (

emp_map, WNDS, WNPS, RNPS, RNDS))

/

CREATE OR REPLACE TYPE BODY EMP_T as

MAP MEMBER FUNCTION EMP_MAP

RETURN VARCHAR2 IS

BEGIN

RETURN LNAME_TX || FNAME_TX;

END;

END;

/

CREATE TABLE EMP OF EMP_T;

INSERT INTO EMP VALUES (1,'SMITH','AL');

INSERT INTO EMP VALUES (2,'BRIER','JIM');

INSERT INTO EMP VALUES (3,'MARKS','TIM');

SQL> SELECT * FROM EMP;

EMP_ID LNAME_TX FNAME_TX

--------- ---------- ----------

1 SMITH AL

2 BRIER JIM

3 MARKS TIM

SQL> SELECT * FROM EMP E

2 ORDER BY VALUE (E);

EMP_ID LNAME_TX FNAME_TX

--------- ---------- ----------

2 BRIER JIM

3 MARKS TIM

1 SMITH AL

An example of an order method is shown in the following code:

CREATE OR REPLACE TYPE EMP_T

AS OBJECT (

EMP_ID NUMBER (10),

LNAME_TX VARCHAR2(10),

FNAME_TX VARCHAR2(10),

ORDER MEMBER FUNCTION

EMP_MAP(IN_EMP IN EMP_T) RETURN INTEGER,

PRAGMA RESTRICT_REFERENCES (

EMP_MAP, WNDS, WNPS, RNPS, RNDS))

/

CREATE OR REPLACE TYPE BODY EMP_T IS

ORDER MEMBER FUNCTION EMP_MAP

(IN_EMP EMP_T) RETURN INTEGER IS

SELF_EMP VARCHAR2 (60) := SELF.LNAME_TX ||

SELF.FNAME_TX;

V_EMP VARCHAR2 (60) := IN_EMP.LNAME_TX ||

IN_EMP.FNAME_TX;

BEGIN

IF SELF_EMP < V_EMP THEN

RETURN -1;

ELSIF SELF_EMP > V_EMP THEN

RETURN 1;

ELSE RETURN 0;

END IF;

END;

END;

/

CREATE TABLE EMP OF EMP_T;

SQL> SELECT * FROM EMP;

EMP_ID LNAME_TX FNAME_TX

--------- ---------- ----------

1 SMITH AL

2 BRIER JIM

3 MARKS TIM

SQL> SELECT * FROM EMP E

2 ORDER BY VALUE (E);

EMP_ID LNAME_TX FNAME_TX

--------- ---------- ----------

2 BRIER JIM

3 MARKS TIM

1 SMITH AL

 

User-Defined (Member) Methods

User-defined methods are user-defined access paths that declare the valid reporting and data manipulation guidelines for a specific object class. User-defined methods are physically implemented as PL/SQL procedures and/or functions, defined as part of the object type specification. User-defined methods are intended for data retrieval activity such as a function to accept a person’s birth date and compute their age. Today we can create user-defined methods that simulate this functionality. But to do so, we must either hard-code the name of the table in a DML statement embedded within the member method, or use dynamic SQL.

Although DML statements can be embedded within user-defined methods, Oracle does not suggest using this strategy. User-defined constructor method capability is being planned for future Oracle8 releases. If you intend to embed DML statements within member methods, you can do so either explicitly by naming the table within the DML statement, or by issuing the DML statement using dynamic SQL.

Object Tables

Object tables are tables whose structure is based on object types. In Oracle8i, object tables are tightly bound to the object type that they are instantiated upon. Object tables are not truly object-oriented. You cannot add columns to object tables directly. Rather, you must add them to the object type that the object table is based upon. The object table structure must not deviate from the structure of its object type. A future release of Oracle8 will support reclassifying an object table as a different object type via the ALTER_TABLE command.

An example of code to create an object table follows:

CREATE OR REPLACE TYPE NAME_T

AS OBJECT (

COL VARCHAR2 (30))

/

CREATE OR REPLACE TYPE EMP_T

AS OBJECT (

EMP_ID NUMBER (10),

LNAME_TX NAME_T,

FNAME_TX NAME_T,

BIRTH_DT DATE)

/

CREATE TABLE EMP OF EMP_T (

EMP_ID NOT NULL,

LNAME_TX NOT NULL,

FNAME_TX NOT NULL,

BIRTH_DT NOT NULL,

PRIMARY KEY (EMP_ID))

/

INSERT INTO EMP VALUES(

34532,

NAME_T('SMITH'),

NAME_T('JOHN'),

'25-DEC-1965')

/

 

Collections

Collections are a means of storing a series of data entries that are jointly associated to a corresponding row in the database. They are used for small numbers of occurrences. Collections model a one-to-many relationship between a row and a collection without necessitating integrity constraints. Oracle8 now offers two additional techniques for closely associating rows between two object classes. These two techniques are nested tables and VARRAYS. Nested tables are based on object types and do not store their data in the same location as the master table. Nested tables appear to have more performance benefits than VARRAYS, because a full scan of a table including a VARRAY must scan the contents of the VARRAY, while querying a table that contains a nested table would not require scanning of the nested table itself. On the other hand, data stored within a VARRAY is stored in the same location as the data of the master table, resulting in maximum retrieval efficiency.

VARRAYS

VARRAYS, or varying arrays are typically stored inline with respect to their containing row. VARRAYS are assigned an outer limit of values. VARRAYS have the following characteristics:

An example of code to create a VARRAY is as follows:

CREATE OR REPLACE TYPE SALES_T AS VARRAY (3) OF NUMBER (10,2)

/

CREATE TABLE DAILY_SALES (

DAILY_SALES_ID INTEGER,

DAILY_SALES_AMT SALES_T)

/

INSERT INTO DAILY_SALES VALUES (1,SALES_T(98347.23))

/

 

Nested Tables

Nested Tables, the second collection type seem vaguely similar to the notion of clustered tables from Oracle7, though they are not implemented in the same manner. A nested table is essentially an additional relational table. It is not stored inline with the master table, as clustered tables do. Therefore, nested tables do not inherently offer a performance benefit. Nested tables have the following characteristics:

Nested tables cannot be limited as VARRAYs can. Querying nested tables in general will be more efficient with nested tables as opposed to VARRAYs, because you can create secondary indexes on nested tables.

 

Index Organized Tables (IOTs)

In IOT tables, rows are physically clustered (and ordered) on the primary key. Index Organized tables should be used when you plan to query detail rows by the master rows. You can store the entire contents of a table in the index structure. IOTs only requires a hit to the table index, not index to get ROWID to hit table. Object Tables cannot be stored as Index Organized tables in Oracle8i, though this functionality may become available in a future release. Index Organized tables should be used when you plan to query detail rows by the master rows. In fact, coupled with nested tables, IOTs out-perform clusters. A proposed example of the code to create an IOT nested table is shown below. This feature is not expected to be supported until Oracle8i.

CREATE OR REPLACE TYPE

PO_DTL_TYPE AS OBJECT (

ITEM_ID VARCHAR2 (5),

QTY NUMBER (5))

/

CREATE OR REPLACE TYPE PO_DTL_TABLE_TYPE

AS TABLE OF PO_DTL_TYPE

/

CREATE OR REPLACE TYPE

PO_TYPE AS OBJECT (

PO_ID VARCHAR2 (5),

DESCR_TX VARCHAR2 (40),

VENDOR_ID VARCHAR2 (5),

PO_DTL PO_DTL_TABLE_TYPE)

/

CREATE TABLE PO OF PO_TYPE(

PO_ID NOT NULL PRIMARY KEY,

DESCR_TX NOT NULL,

VENDOR_ID NOT NULL)

NESTED TABLE PO_DTL STORE AS PO_DTL

(PRIMARY KEY (NESTED_TABLE_ID) ORGANIZATION INDEX

RETURN AS LOCATOR

/

 

Partitioned Tables

In Oracle8i we have the ability to partition tables. This means that we can dictate where each record is physically stored, giving us the ability to group rows logically by the manner in which they are generally accessed. With partitioned tables, organized data storage can be done using common retrieval tactics. Partition specification cannot be dynamic, for example

to_char(TRANS_DATE,’MMYYYY’)=‘011998’

The following code shows how to partition a table:

CREATE TABLE TRANSACTIONS (

TRANSACTION_ID VARCHAR2 (15) NOT NULL,

CARDHOLDER VARCHAR2 (60) NOT NULL,

SIC VARCHAR2 (5) NOT NULL,

PURCHASE_AMT NUMBER(9,2) NOT NULL,

TRANSACTION_DT DATE NOT NULL)

PARTITION BY RANGE (TRANSACTION_DT)

(PARTITION TRANS1 VALUES LESS THAN (TO_DATE('0201998','MMDDYYYY'))

TABLESPACE TRANS1_TS,

PARTITION TRANS2 VALUES LESS THAN (TO_DATE('03011998','MMDDYYYY'))

TABLESPACE TRANS2_TS)

/

 

DEFERRED and NOVALIDATE Constraints

The DEFERRED and NOVALIDATE options are a pair of similar features that are geared to manipulating the validation performed by integrity constraints. The DEFERRED option is a parameter of the SET CONSTRAINTS command, issued from within a SQLPLUS session. The two values this parameter accepts are IMMEDIATE and DEFERRED.

By default , this command is set to IMMEDIATE, which means that the RDBMS will validate the constraint immediately. DEFERRED provides the ability to pass validation of constraints until a COMMIT is issued. The DEFERRED option is generally useful in situations such as PO and PO_DTL, where you may wish to perform DML operations on multiple, related tables simultaneously, with no assurance as to the order these transactions will be validated.

The NOVALIDATE constraint clause, however, provides far more flexibility, specifically targeted to databases having new constraints being added, or databases where large data migrations are taking place. NOVALIDATE constraints enable new constraints that disregard prior integrity violations. An example is shown below:

ALTER TABLE EMP ENABLE NOVALIDATE CONSTRAINT EMP__STATE_FK;

Object Views

An object view is very similar to a relational view. Object views are based upon a single SELECT statement that could reference one or more relational and/or object-relational tables. The most common use of views is still primarily for providing a secure level of the actual data structures. The benefit of using object views is that they serve as a migration path between relational design and object-relational design. You can create object views that are based upon object types, and access data stored in relational tables. This allows utilization of object references and methods in conjunction with your relational data, without changing any data structures.

Essentially, you can maintain existing relational applications, and add an object layer on top of them at your convenience, providing an excellent opportunity to compare and contrast the two techniques in your own environment. Object views enable you to effectively use Oracle8 objects without having to migrate your existing relational data.

Object views are typed strongly, as are object tables. In other words, both object views and object tables must be instantiated as a single object type, and their structure can never deviate from that object type. Object types simulate encapsulation and can be used to access OIDs. Sample code to create an object view is shown below:

CREATE TABLE DEPARTMENTS (

DEPT_ID NUMBER (10) NOT NULL PRIMARY KEY,

NAME VARCHAR2 (50) NOT NULL);

CREATE OR REPLACE TYPE DEPT_T AS OBJECT (

DEPT_ID NUMBER (10),

NAME VARCHAR2 (50));

/

CREATE VIEW OV_DEPT OF DEPT_T WITH OBJECT OID (DEPT_ID)

AS SELECT DEPT_ID, NAME

FROM DEPARTMENTS

/

 

INSTEAD_OF Triggers

INSTEAD-OF fire instead of the actual DML statement. For example, you can write an INSTEAD_OF trigger to replace Oracle’s Insert functionality. This is new with Oracle8i and is only available for views. Some characteristics of these triggers are as follows:

 


Large Objects (LOBS)

Large Objects (LOBS) are new data types available with the release of Oracle 8.0. LOBs provide substantially greater storage ability as compared to their predecessor, LONG. LOBS can store up to 4GB of data in raw, binary or textual format. They can essentially be stored in line (up to 4k) within a row, or otherwise out of line. There are a number of different data types that correspond to LOBS:

Data can also be stored inside a LOB. For example, you might want to store secure data such as salaries in a LOB, because LOB data is not directly accessible from SQL. It is essentially stored in an uninterpreted, binary format. The suggested approach to viewing data stored within a LOB would be through the implementation of Methods. Methods are PL/SQL; and PL/SQL is required to view/manipulate data stored within LOBs. You can also perform context-sensitive querying of LOBS, such as requesting the first 500 characters of the column where LONGs required return of entire value, or occurrences where = ‘STRING’. You can have multiple LOBs in a single table, unlike LONGs, which were limited to one per table.

Some characteristics of LOBs include the following:

The following descriptions apply to LOB packages and Datatypes:

LOB Packages

The following LOB Packages can be used in Oracle8i:

Implementing LOBs

LOBs can be implemented as follows:

Columns in table

Attributes of an object (except NCLOBS)

An example of a table containing multiple LOB’s is shown below:

CREATE TABLE LOB_TABLE (

ID INTEGER,

B_LOB BLOB,

C_LOB CLOB,

N_LOB NCLOB,

F_LOB BFILE);

Performance Tip: Store LOB in separate tablespace from the table it is associated with

 

LOB Parameters

The following are parameters that may be applied to LOBs:

To initialize internal LOBS, the following code can be used:

CREATE TABLE LOB_TABLE (

ID INTEGER,

B_LOB BLOB,

C_LOB CLOB,

N_LOB NCLOB,

F_LOB BFILE);

INSERT INTO LOB_TABLE VALUES(

1,

EMPTY_BLOB(), --Empty Value zero length value

NULL, --Null Value no length value

EMPTY_CLOB(), --Empty Value zero length value

NULL); --Null Value no length value

If LOB value is unavailable at INSERT, set to EMPTY when you need to access with OCI or DBMS_LOB, because these require a locator.

BFILE

The following characteristics apply to BFILE large objects:

Caution should be used when creating or dropping any directory.

 

Server Side Code

Oracle8i offers the ability to develop and store server-side Java code within the database. These Java program units can be executed from PL/SQL triggers, procedures, and/or functions. Uncompiled Java code offers reasonably comparable performance to PL/SQL, though not quite as good, given the number of years that have gone into the optimization of PL/SQL within the server.

However, compiled Java code can execute up to 10-15 times faster than PL/SQL. Couple this statistic with the fact that Java is extremely portable, and you can see a new trend. As is the case with relational data structures, PL/SQL will not go away. There are far too many systems already that are based upon PL/SQL, and many more are in development. PL/SQL is a robust, veteran programming language that has served us well for a number of years.

Keep in mind, however, that there are several organizations worldwide working to make Java as efficient as possible. The collection of these resources will most likely provide an end product with superior performance and usability not easily matched by any single organization. Do not be surprised if before long we can create database triggers, procedures, and functions written in Java, as opposed to simply referencing Java.

Conclusion

Unfortunately, this paper will be out of date by the time June has rolled around. This is primarily due to the fact that Oracle8i has not yet been released at the time of writing. It is the author’s expectation that a number of the issues pointed out in this paper have been fixed as of 8i, and I hope to be able to confirm this prior to the presentation. Although I will not be implementing an entirely ORDBMS system in the next few months, there are some features, such as Column Types, that we can and will take immediate advantage of. Despite its limitations, the Oracle 8i Object Layer is a step in the right direction toward more object-oriented databases.

© 1999 Dulcian, Inc.