New CONNECT by Features in Oracle Database 10g

4

Click here to load reader

description

New CONNECT

Transcript of New CONNECT by Features in Oracle Database 10g

Page 1: New CONNECT by Features in Oracle Database 10g

New CONNECT BY Features in Oracle Database 10g http://www.oracle.com/technology/oramag/webcolumns/2003/techarticl...

1 di 4 15/02/2007 11.47

(Sign In / Register for a free Oracle Web account)

Technology NetworkTechnology Network

PRODUCTSDatabase

Middleware

Developer Tools

Enterprise Management Applications Technology

Extensions and Plugins

Products A-Z

TECHNOLOGIESBI & Data Warehousing

JavaLinux

.NET

Office

PHPSecurity

Service-Oriented Architecture

XML

Windows Server SystemTechnologies A-Z

COMMUNITYAbout OTNOracle ACEs

Regional Directors

Blogs

PodcastsTechBlast Newsletter

Oracle Magazine

Oracle 10g BooksCertification

User Groups

Partner White Papers

Legal | Privacy

SELECT COUNTRYSELECT COUNTRY

Getting Started

Downloads Documentation Forums ArticlesSample Code

Tutorials

Inside Oracle Database 10g

New CONNECT BY Features in Oracle Database 10g

By Jonathan GennickOTN Member since 2001

Oracle Database 10g enhances support for querying hierarchical, or tree-structured, data

Recently I wrote about Oracle's support for hierarchical queries in an OTN article titled Querying Hierarchies: Top-of-the-Line Support. While writing that article, I learned about some exciting, new features in Oracle Database 10g that strengthen Oracle's already robust support for querying tree-structured data. Unfortunately, I couldn't mention those new features because they were still in beta. Since then, I've been rather impatiently biding my time until the product announcement, and now the day has come when I can speak freely.

This article details the three new CONNECT BY features in Oracle Database 10g. The examples are based on the same table, and use the same data, as those in my previous article. You may wish to read that article to refresh your memory as to how CONNECT BY queries work.

Root of the Matter

If you read my previous article, you've seen how the PRIOR operator is used in hierarchical queries to return column data from a parent row. Sometimes it's handy to be able to go all the way back to the root row. New in Oracle Database 10g, the CONNECT_BY_ROOT operator enables you to reference root-row values from anywhere in a hierarchy.

One use for CONNECT_BY_ROOT is to identify all products containing a given part. Suppose you work for a manufacturing company. You've just discovered that part 1019 is defective, and the Consumer Product Safety Commission has ordered you to recall all products sold containing that part. Your first task is to determine just which products you need to worry about. You could begin by issuing the following query, as a first attempt:

SELECT assembly_id, assembly_nameFROM bill_of_materialsWHERE part_number = 1019START WITH parent_assembly IS NULLCONNECT BY parent_assembly = PRIOR assembly_id;

ASSEMBLY_ID ASSEMBLY_NAME

----------- ----------------------- 141 Lock 144 Lock

These results look plausible, but there's one problem with them. Part 1019 is a lock, and it's indeed used in two lock assemblies. However, those lock assemblies are in turned used within left and right door assemblies, which are in turn used in a body assembly, which is ultimately used to make a car, and it's cars that we sell and care about. You don't want the immediate parent assembly for part 1019; you want the ultimate parent for part 1019. Fortunately, your DBA just upgraded to Oracle Database 10g, so you can take advantage of the new CONNECT_BY_ROOT operator:

SELECT DISTINCT CONNECT_BY_ROOT assembly_id, CONNECT_BY_ROOT assembly_nameFROM bill_of_materialsWHERE part_number = 1019START WITH parent_assembly IS NULLCONNECT BY parent_assembly = PRIOR assembly_id;

CONNECT_BY_ROOTASSEMBLY_ID CONNECT_BY_ROOTASSEMBLY-------------------------- -----------------------

secure search

Page 2: New CONNECT by Features in Oracle Database 10g

New CONNECT BY Features in Oracle Database 10g http://www.oracle.com/technology/oramag/webcolumns/2003/techarticl...

2 di 4 15/02/2007 11.47

100 Automobile

The bulk of this query is the same as before. There are just two differences: the use of DISTINCT , and the presence of CONNECT_BY_ROOT in front of each column name in the SELECT list. The CONNECT_BY_ROOT operator yields the ultimate parent assembly IDs and names for the part we're concerned about. The DISTINCT keyword prevents a product from being listed multiple times if it contains the same part in more that one assembly. It turns out that your automobile contains locks in both its right and left doors.

Getting to the Bottom of Things

Hierarchical data is often deeply nested. Consider the problem of presenting a mechanic with a nested list of assemblies and parts that go into a car. Cars contain large numbers of parts. Rarely will a mechanic want to see details on all the assemblies and parts in a car at once. Not only would such a list be overwhelming, but it's very inefficient to retrieve such a complete list of assemblies and parts from a database and transmit that information across the network when the user wants only a fraction of that data. Instead, you might choose to present only the top-level of assemblies to begin with, and let users drill-down from there. For example, perhaps you initially present our user with the results of the following query:

SELECT ASSEMBLY_ID, RPAD(' ', 2*(LEVEL-1)) || assembly_name asse mbly_name, quantityFROM bill_of_materialsWHERE LEVEL <= 2START WITH assembly_id = 100CONNECT BY parent_assembly = PRIOR assembly_id;

ASSEMBLY_ID ASSEMBLY_NAME QUANTITY

----------- ------------- ---------- 100 Automobile 110 Combustion Engine 1 120 Body 1 130 Interior 1

Looking at this first level of assemblies, our users can now decide whether they want to drill down further. You can enable drill-down by implementing assembly names as web links when there's more data to be seen, or you can implement a tree control such as is commonly seen in Windows applications. But wait! How do you know when there's more data for an assembly? When is drill-down possible? You could let users try to drill-down into any assembly, and give them a "no more data" message when they try to drill-down from the bottom of the hierarchy, but that's an inelegant solution certain to frustrate them. It's better to know ahead of time whether drill-down is possible. Oracle Database 10g enables us to do that via the CONNECT_BY_ISLEAF pseudocolumn. You can use the following query to begin:

SELECT ASSEMBLY_ID,

RPAD(' ', 2*(LEVEL-1)) || assembly_name asse mbly_name, quantity, CONNECT_BY_ISLEAFFROM bill_of_materialsWHERE LEVEL <= 2START WITH assembly_id = 100CONNECT BY parent_assembly = PRIOR assembly_id;

ASSEMBLY_ID ASSEMBLY_NAME QUANTITY CONN ECT_BY_ISLEAF----------- ----------------------- ---------- ---- ------------- 100 Automobile 0 110 Combustion Engine 1 0 120 Body 1 0 130 Interior 1 0

The zeros returned by CONNECT_BY_ISLEAF indicate that none of the assemblies shown in this listing are leaf nodes. In other words, it's valid to drill down into any of them. Say a user drills down into Combustion Engine. You then issue the following query to get the subassemblies making up an engine:

SELECT ASSEMBLY_ID, RPAD(' ', 2*(LEVEL-1)) || assembly_name asse mbly_name,

Page 3: New CONNECT by Features in Oracle Database 10g

New CONNECT BY Features in Oracle Database 10g http://www.oracle.com/technology/oramag/webcolumns/2003/techarticl...

3 di 4 15/02/2007 11.47

Next Steps

Download the Oracle Database:/software/products/oracle9i/index.html

Visit the Oracle Database 10gProduct Page::/products/database/index.html

quantity, CONNECT_BY_ISLEAFFROM bill_of_materialsWHERE LEVEL = 2START WITH assembly_id = 110CONNECT BY parent_assembly = PRIOR assembly_id;

ASSEMBLY_ID ASSEMBLY_NAME QUANTITY CONN ECT_BY_ISLEAF----------- ----------------------- ---------- ---- ------------- 111 Piston 6 1 112 Air Filter 1 1 113 Spark Plug 6 1 114 Block 1 1 115 Starter System 1 0

This query is almost the same as before. The START WITH assembly_id value has been changed to 110, for Combustion Engine, and the query specifically asks for LEVEL = 2. You don't need LEVEL = 1 at this point, because that would return the row for Combustion Engine again, and you already have that row.

This time, you see two values for CONNECT_BY_ISLEAF. The value of 1 for Piston, Air Filter, Spark Plug and Block indicates that those assemblies are leaf nodes under which no more assemblies are to be found. Knowing that, you can adjust our display so the user knows not to bother drilling down on those elements. On the other hand, the Starter System has a CONNECT_BY_ISLEAF value of 0, indicating that there are still subassemblies to be retrieved.

Getting Out of the Loop

Whenever you work with hierarchical data, there's the chance you might encounter a hierarchy that's circular. For example, someone might set the parent of an automobile to be a spark plug:

UPDATE bill_of_materialsSET parent_assembly = 113WHERE assembly_id=100;

An attempt to query the tree of assemblies for "Automobile" will now fail:

SELECT RPAD(' ', 2*(LEVEL-1)) || assembly_name asse mbly_name,

quantityFROM bill_of_materialsSTART WITH assembly_id = 100CONNECT BY parent_assembly = PRIOR assembly_id;

ERROR:ORA-01436: CONNECT BY loop in user data

When you get an error message like this, you can use the CONNECT_BY_ISCYCLEpseudocolumn to locate the row (or rows) causing the problem. To do that, you must also add the NOCYCLE keyword to the CONNECT BY clause, to prevent the database from following any loops in the hierarchy:

SELECT RPAD(' ', 2*(LEVEL-1)) || assembly_name asse mbly_name, quantity, CONNECT_BY_ISCYCLEFROM bill_of_materialsSTART WITH assembly_id = 100CONNECT BY NOCYCLE parent_assembly = PRIOR assembly _id;

ASSEMBLY_NAME QUANTITY CONNECT_B Y_ISCYCLE------------------------------ ---------- --------- ---------Automobile 0

Combustion Engine 1 0 Piston 6 0 Air Filter 1 0 Spark Plug 6 1 Block 1 0

Note that CONNECT_BY_ISCYCLE returns a 1 for the "Spark Plug" row. When you use

Page 4: New CONNECT by Features in Oracle Database 10g

New CONNECT BY Features in Oracle Database 10g http://www.oracle.com/technology/oramag/webcolumns/2003/techarticl...

4 di 4 15/02/2007 11.47

E-mail this page

Printer View

NOCYCLE, the database keeps track of its path through the hierarchy, constantly checking to ensure it's not following a loop. After working it's way from "Automobile" to "Combustion Engine" to "Spark Plug", the database sees that "Spark Plug's" child is "Automobile," a row that is already in the path taken to get to "Spark Plug". Such a row represents a loop. NOCYCLEprevents the database from following the loop, and CONNECT_BY_ISCYCLE returns a 1 to identify the row in which the loop occurs. Now that you know where the problem is, you can fix it.

Getting Work Done

The new CONNECT BY features in Oracle Database 10g—CONNECT_BY_ROOT, CONNECT_BY_ISLEAF, and CONNECT_BY_ISCYCLE—are well thought out and welcomeimprovements to Oracle's hierarchical query support. These features solve common andlongstanding problems inherent in querying hierarchical data, problems that are difficult to solveotherwise. Using these features, you can focus less on implementation details and more on thebig picture of what you need to accomplish, getting work done that you need done simply andwithout fuss.

Jonathan Gennick ([email protected]) is an experienced Oracle DBA and an Oracle Certified Professional. He resides in Munising, Mich., and just finished writing the Oracle Regular Expression Pocket Reference (O'Reilly & Associates, 2003) with Peter Linsley. Jonathan also runs an email list for articles about Oracle, which you can subscribe to by visiting http://gennick.com.