BC remote Oracle DBA - Call (800) 766-1884  
Oracle Consulting Oracle Training Development

Remote DBA

Remote DBA Plans  

Remote DBA Service

Remote DBA RAC

   
Remote DBA Oracle Home
Remote DBA Oracle Training
Remote DBA SQL Tuning Consulting
Remote DBA Oracle Tuning Consulting
Remote DBA Data Warehouse Consulting
Remote DBA Oracle Project Management
Remote DBA Oracle Security Assessment
Remote DBA Unix Consulting
Burleson Books
Burleson Articles
Burleson Web Courses
Burleson Qualifications
Oracle Links
Remote DBA Oracle Monitoring
Remote DBA Support Benefits
Remote DBA Plans & Prices
Our Automation Strategy
What We Monitor
Oracle Apps Support
Print Our Brochure
Contact Us (e-mail)
Oracle Job Opportunities
Oracle Consulting Prices





   

 

 

 

Remote DBA services

Remote DBA Support

Remote DBA RAC

Remote DBA Reasons

Remote Oracle Tuning

Remote DBA Links

Oracle DBA Support

Oracle DBA Forum

Oracle Disaster

Oracle Training

Oracle Tuning

Oracle Training

 Remote DBA SQL Server

Remote MSSQL Consulting

Oracle DBA Hosting

Oracle License Negotiation

 

 


 

 

 

 

 

 
 

Establishing Data Relationships to Other Tables with Pointers

Oracle Tips by Burleson Consulting

We have now violated first normal form and upset Chris Date, let's carry this argument one step further.  If it is possible to allow for repeating values within a table cell, why not a reference to an entirely new table?  Imaging a database which allows nesting of tables within tables such that a single cell of one table could be a pointer to another whole table.  While this concept may seem very foreign on the surface, it is not too hard to understand if we consider that many real-world "things”, or objects, are made up of sub-parts. 

A special note on pointers.  In order to establish data relationships between database entities, a pointer must be persistent, unique and non-expiring.  In pre object/relational databases a relational Row ID was used to identify a row.  Unfortunately, this Row ID was the number of the physical database block and row displacement within the data block.  As such, a relational row could “move” to another block as a result of routine maintenance, or be deleted.  To address this problem, the object/relational vendors have devised a way to create OIDs for each row that will always uniquely identify a row, regardless of the row’s status.  For example, a database row could be deleted, and the OID that was associated with that row will never be re-used by the database software.

To create a table with OIDs, a data type must be created that contains all of the necessary row information.  In the following example, assume that the data type customer_stuff contains all of the required data structures for a customer table.  In a traditional relational database, we could create the table like this:

CREATE TABLE customer (customer_data         customer_stuff);

With the introduction of OIDs, the table creation syntax has changed slightly.  The following example will create the exact same table as our earlier example, with the exception that the table will contain an OID for each row that is created within the customer table:

CREATE TABLE customer OF customer_stuff;

It has always been a shortcoming of the relational model that only atomic things could be directly represented, and relational "views" were required to assemble aggregate objects. The object technology professors always used to make fun of the relational model's inability to represent aggregate objects, stating that it would be like disassembling your car each evening when you are done driving it, only to re-assemble your car each time that you want to drive it.  At last, nested abstract data types allow Oracle users to represent real-world "things" without resorting to views.

Let's take a look at how this type of recursive data relationship might be represented within an object/relational database.  The following SQL creates a TYPE definition for a list of orders.  This list of pointers to orders might become a column within an Oracle table.

CREATE TYPE order_set
    AS TABLE OF order;

CREATE TYPE CUSTOMER_STUFF (
    customer_id                 integer,
    customer_full_name    full_name,
    customer_full_address customer_address,
    . . . 
    order_list                      order_set);

CREATE TABLE customer OF customer_stuff;

Here we see the new style of table creation syntax.  Both of the following table declarations are identical, except that the CREATE TABLE OF syntax will establish the Object ID’s so that other tables may contain references to rows in the customer table.

Without OID’s:             CREATE TABLE customer (cust_data   customer_stuff);
With OID’s:                 CREATE TABLE customer OF customer_stuff;

In either case, we have now defined a pointer column called order_list in the customer table.  This pointer will point to a list of pointers.  Each cell of this list will contain pointers to rows in the order  table.  (Figure 6.2)

Figure 6.2  Pointers to other database rows.

While figure 6.2 shows the pointer structure as it would look conceptually, the object/relational databases  must utilize internal arrays to implement these repeating groups of pointers.  In Oracle, the popular object/relational databases, variable-length arrays are used to represent this structure (Figure 6.3)

Figure 6.3  - The Oracle representation of repeating lists of pointers to rows.

Here we have nested a list of pointers within each column, and that each of the cells within a column contain a list of pointers  to rows in the order table.  Using object-oriented SQL extensions, we can now "pre-join" with the order table to add the three orders for this customer;

 UPDATE customer
    SET order_list (
        select REF(order)    /* this returns the OIDs from all order rows */
        from order
        WHERE
        order_date = SYSDATE
        and
        order.customer_ID = (123)
    )

Here we see the use of the REF operator, which returns the “reference”, or OID of the requested rows.  This is similar to the retrieval of Row ID’s in a relational database, except that we are now storing the row information inside a relational table.

Now let’s take a look at how we can navigate between tables without having to join tables together.  Remember from out earlier discussion, that the object/relational model provides for two ways to retrieve data from our database.  We can use SQL to specify the desired data and let the SQL optimizer choose the access path, or we can navigate our database, one row at a time, and gather the required information.

SELECT DEREF(order_list)
from CUSTOMER
where
customer_id = 123;  /* this will return 3 rows in the order table */

The important point in the above example is that we have navigated between tables without ever performing a SQL join.  Consider the possibilities.  We would NEVER need to embed the foreign key for the customer table in the order record, since we could store the pointers in each customer row.  Of course, we would never be able to perform a relational join between the customer and order tables, but this would not really make any difference as long as we have maintained the ability to navigate between customers and orders with pointers.

Of course, these are one-way pointers from customer to orders, and we would not have a method to get from the order table to the customer table unless we embedded a pointer to point to the row that contains the customer for each order.  We could do this by creating an “owner” reference inside each order row that would contain the OID of the customer who placed the order.

A nineteenth century philosophy professor named Augustus De Morgan create an interesting poem to demonstrate this fundamental truth:

 Great fleas have little fleas
 upon their backs to bite 'em
 And little fleas have lesser fleas,
 and so ad-infinitum

 The great fleas themselves in turn
 has greater fleas to go on,
 while these again have greater still
 and greater still,
 and so on.

Now, let's take a look how this type of recursive data relationship might be represented in an object/relational database such as Oracle:

CREATE TYPE order_set
    AS TABLE OF order;

CREATE TABLE CUSTOMER (
    customer_id                 integer,
    customer_full_name    full_name,
    customer_full_address customer_address,
    . . . 
    order_list                      order_set);

Here we have nested the order table within the customer table!  So, where do we go from here?  How do we populate this new structure?  Let's take a look at how this table might be populated:

INSERT INTO customer VALUES (
    full_name ('ANDREW','S.','BURLESON),
    customer_address('246 1st st.','Minot, ND','74635'); 

Now, we could add three orders for this customer;   

INSERT INTO ORDER values order_id, customer_id, order_date (
    9961
    123,
    SYSDATE); 

INSERT INTO ORDER values order_id, customer_id, order_date (
    9962
    123,
    SYSDATE);

INSERT INTO ORDER values order_id, customer_id, order_date (
    9962
    123,
    SYSDATE);

Now, here comes the best part.  We can now "pre-join" the customer table with the order table to add the three orders for this customer

 UPDATE customer
    SET order_list (
        select REF(order)    /* OID reference */
        from order
        WHERE
        order_date = SYSDATE
        and
        order.customer_ID = (123)
    )

So, what have we got here?  It appears that the order_list entry in the customer table will contain "pointers" to the three orders that have been placed by this customer.   As such, we are able to reference these pointers without having to perform a relational join.

SELECT DEREF(order_list)
from CUSTOMER
where
customer_id = 123;  /* this will return 3 rows in the order table */

This query will return a pointer to the three rows in the order table.  It should then be a simple matter to "de-reference" these pointers to retrieve the contents of the order table.  Depending on the vendor implementation of the SQL, it might look something like this:

SELECT DEREF(order_list)
FROM customer
where customer_ID = 123;

 
If you like Oracle tuning, see the book "Oracle Tuning: The Definitive Reference", with 950 pages of tuning tips and scripts. 

You can buy it direct from the publisher for 30%-off and get instant access to the code depot of Oracle tuning scripts.


Expert Remote DBA

BC is America's oldest and largest Remote DBA Oracle support provider.  Get real Remote DBA experts, call
BC Remote DBA today.

 

 

Remote DBA Service
 

Oracle Tuning Book

 

Advance SQL Tuning Book 

BC Oracle support

Oracle books by Rampant

Oracle monitoring software

 

 

 

 

 

 

BC Remote Oracle Support

Remote DBA

Remote DBA Services

Copyright © 1996 -  2013 by Burleson. All rights reserved.

Oracle® is the registered trademark of Oracle Corporation.



Hit Counter