The Parents And The Order Of Operations


When you build objects in a new environment, you need to build them in the right order of operations.

Until you have all the objects in place, you can’t create a procedure that references them all. And if those objects require more parent objects, they must be created first too. For example:

procedure reads
    view which reads a
       table which is composed of a
          type

—-

Recently I wrote in my other post about the parent and child dependencies. They give a lot of great information. But they only go one level in either direction. As you know, there can be many levels of objects.

What is the order of operations to build them? I’ve written some complex scripts here to find all the successive parents of an object.

The first script I wrote produced some odd results. Interestingly enough, objects can be repeated, a number of times. ie.

PARENT_LVL_OBJID_ROWNUM
------------------------------------------------------------
  PACKAGE BODY  APPS.HR_DELETE   1   278801   1
  PACKAGE BODY  APPS.HR_DELETE   1   278801   2
  PACKAGE BODY  APPS.HR_DELETE   1   278801   3
    SYNONYM  PUBLIC.USER_CATALOG   2   1167   4
      VIEW  SYS.USER_CATALOG   3   1166   5
      VIEW  SYS.USER_CATALOG   3   1166   6
        VIEW  SYS._CURRENT_EDITION_OBJ   4   3270113   7
        VIEW  SYS._CURRENT_EDITION_OBJ   4   3270113   8
  PACKAGE BODY  APPS.HR_DELETE   1   278801   9
    SYNONYM  PUBLIC.DBMS_SQL   2   2328   10
      PACKAGE  SYS.DBMS_SQL   3   2327   11
      PACKAGE  SYS.DBMS_SQL   3   2327   12
      PACKAGE  SYS.DBMS_SQL   3   2327   13
        PACKAGE  SYS.UTL_IDENT   4   3291213   14

...

Of course, this makes sense in some environments. One standard error trapping routine can be called by dozens, and even hundreds of packages and procedures.

What does seem odd, is that, in PUBLIC_DEPENDENCIES, the very same two objects can have multiple dependencies, as you can see here with SYS.USER_CATALOG and SYS._CURRENT_EDITION_OBJ.

————————————————————

This second script gives a distinct set of rows.

————————————————————

fparent_tree.sql

/*

Script to find all successive generations of parents of an object
By Rodger Lepinsky

Will display for example:

procedure
     view
       table
         type
     table
       view

Will show the owner.object_name, level from the child, object_id, and the rownum
on one line for sqlplus

If you prefer, change to:

select object_name
, the_level
, object_id
, the_rownum 

If creating objects in a new environment, start with the highest level first.
Change the order by to:
order by 1 - the_level, the_rownum

The script includes objects owned by:  SYS, SYSTEM, PUBLIC
Comment that line if you want to include them. 

*/

accept ls_obj_name prompt "Enter the exact object name:  " ;

select  ao.object_type || '  '  || ao.OWNER || '.' ||
        ao.OBJECT_NAME  as object
, max (pd.OBJECT_ID) as object_id
from  all_objects  ao
join PUBLIC_DEPENDENCY pd
   on pd.object_id  = ao.object_id
join  all_objects  ao2
   on  ao2.object_id  = pd.REFERENCED_OBJECT_ID
where  ao.OBJECT_NAME = upper(  '&ls_obj_name' )     /* parent */
and  ao2.OWNER not IN ('SYS', 'SYSTEM')
group by ao.object_type || '  '  || ao.OWNER || '.' ||
        ao.OBJECT_NAME
/

accept ls_obj_id prompt "From above, enter the exact object_id:  " ;

select object_name
   || '   '    ||  the_level
   || '   '    ||  object_id
   || '   '    ||  the_rownum
    as  parent_lvl_objid_rownum
from
   (
   select  object_name     as object_name
   , OBJECT_ID
   , the_level
   , min (the_rownum)  as the_rownum
   from
       (  /* By Rodger Lepinsky */
       SELECT     LPAD(' ', 2*(LEVEL-1)) || '  '  ||
       ao.OBJECT_type || '  '  ||  ao.owner || '.' ||
       ao.object_name  || '   ' || ao.OBJECT_ID || '  ' || rownum
                AS THE_TREE
       , LPAD ( ' ', 2*(LEVEL-1) ) || '  '  ||
         ao.OBJECT_type || '  ' ||
         ao.owner ||  '.' ||
         ao.object_name
              as object_name
       , ao.owner ||  '.' || ao.object_name
            as object_name2
       , ao.OBJECT_type
       , ao.OBJECT_ID
       , ao.owner
       , rownum as the_rownum
       , level as the_level
       FROM               PUBLIC_DEPENDENCY   pd
       join         all_objects  ao
            on    ao.object_id   = pd.object_id
/*       where ao.owner NOT in  ( 'SYS', 'SYSTEM', 'PUBLIC' )    */
       START WITH         pd.OBJECT_ID =  &ls_obj_id
       CONNECT BY PRIOR   pd.REFERENCED_OBJECT_ID = pd.OBJECT_ID
      )
   group by object_name, object_id, the_level
   )
order by the_rownum
/

Here is some output:

PARENT_LVL_OBJID_ROWNUM
-------------------------------------------------------------------------
  PACKAGE BODY  APPS.HR_DELETE   1   278801   1
    SYNONYM  PUBLIC.USER_CATALOG   2   1167   4
      VIEW  SYS.USER_CATALOG   3   1166   5
        VIEW  SYS._CURRENT_EDITION_OBJ   4   3270113   7
    SYNONYM  PUBLIC.DBMS_SQL   2   2328   10
      PACKAGE  SYS.DBMS_SQL   3   2327   11
        PACKAGE  SYS.UTL_IDENT   4   3291213   14
    SYNONYM  APPS.FND_LOOKUP_VALUES   2   90783   16
    SYNONYM  APPS.FND_LOOKUP_TYPES   2   90784   18
    SYNONYM  APPS.FND_PROFILE_OPTION_VALUES   2   91033   20
    SYNONYM  APPS.FND_PROFILE_OPTIONS   2   91036   22
...

    SYNONYM  APPS.PER_APPLICATIONS   2   92201   138
    SYNONYM  APPS.PER_ADDRESSES   2   92203   140
      TABLE  HR.PER_ADDRESSES   3   38985   141
        TYPE  MDSYS.SDO_ORDINATE_ARRAY   4   24452   143
        TYPE  MDSYS.SDO_ELEM_INFO_ARRAY   4   24453   145
        TYPE  MDSYS.SDO_GEOMETRY   4   24454   147
          TYPE  MDSYS.SDO_POINT_TYPE   5   24451   149
          TYPE  MDSYS.SDO_ORDINATE_ARRAY   5   24452   151
          TYPE  MDSYS.SDO_ELEM_INFO_ARRAY   5   24453   153
    SYNONYM  APPS.PER_ABS_ATTENDANCE_REASONS   2   92204   155
    SYNONYM  APPS.PER_ABSENCE_ATTENDANCE_TYPES   2   92205   157-------------------

----

——————-

At one place I worked at, there was a number of coworker who, who had 10 or 15 years of “experience” with Oracle. One week, there was a big migration of objects to the production environment, with many objects to be created. An “experienced” coworker, struggled with the creation script over 2 or 3 days! Later I realized that the reason she struggled so much, was that she actually wrote the script using guessing, and trial and error. She still did not know how to query the data dictionary!

—-

So, this script should be very useful in some environments!

Advertisements

2 Responses to The Parents And The Order Of Operations

  1. For me the dependencies on TABLE objects are not shown.
    I have addapted the script in a way that it works for me now:

    select ao.object_type || ‘ ‘ || ao.OWNER || ‘.’ ||
    ao.OBJECT_NAME as object
    , max (ao.OBJECT_ID) as object_id
    from all_objects ao
    join PUBLIC_DEPENDENCY pd
    on pd.REFERENCED_OBJECT_ID = ao.object_id
    join all_objects ao2
    on ao2.object_id = pd.object_id
    where ao.OBJECT_NAME = upper( ‘V_ET_ZEICHNUNGEN_TP’ ) /* parent */
    and ao2.OWNER not IN (‘SYS’, ‘SYSTEM’)
    group by ao.object_type || ‘ ‘ || ao.OWNER || ‘.’ ||
    ao.OBJECT_NAME;

    select object_name
    || ‘ ‘ || the_level
    || ‘ ‘ || object_id
    || ‘ ‘ || the_rownum
    as parent_lvl_objid_rownum
    from
    (
    select object_name as object_name
    , OBJECT_ID
    , the_level
    , min (the_rownum) as the_rownum
    from
    (
    SELECT LPAD(‘ ‘, 2*(LEVEL-1)) || ‘ ‘ ||
    ao.OBJECT_type || ‘ ‘ || ao.owner || ‘.’ ||
    ao.object_name || ‘ ‘ || ao.OBJECT_ID || ‘ ‘ || rownum
    AS THE_TREE
    , LPAD ( ‘ ‘, 2*(LEVEL-1) ) || ‘ ‘ ||
    ao.OBJECT_type || ‘ ‘ ||
    ao.owner || ‘.’ ||
    ao.object_name
    as object_name
    , ao.owner || ‘.’ || ao.object_name
    as object_name2
    , ao.OBJECT_type
    , ao.OBJECT_ID
    , ao.owner
    , rownum as the_rownum
    , level as the_level
    FROM PUBLIC_DEPENDENCY pd
    join all_objects ao
    on ao.object_id = pd.REFERENCED_OBJECT_ID
    join all_objects ao2
    on ao2.object_id = pd.object_id
    /* where ao.owner NOT in ( ‘SYS’, ‘SYSTEM’, ‘PUBLIC’ ) */
    START WITH pd.OBJECT_ID = 99420
    CONNECT BY PRIOR pd.REFERENCED_OBJECT_ID = pd.OBJECT_ID
    )
    group by object_name, object_id, the_level
    )
    order by the_rownum;

  2. rodgersnotes says:

    As you know, DBA_DEPENDENCIES only go one layer up or down.

    So, if you have multiple layers, you have to do recursive queries.

    I’ve since been looking at solving this problem using the graph database, Neo4J. See one initial article here:

    https://rodgersnotes.wordpress.com/2013/07/31/dba_objects-tree-modelled-as-a-graph/

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: