views:

47

answers:

1

Ok, I have a complex recursion problem. I want to get a dependecy installation sequence of all of my objcts (all_objects table) in my Oracle 11g database.

First I have created a view holding all dependencies

create or replace 
view REALLY_ALL_DEPENDENCIES as
select * 
  from ALL_DEPENDENCIES
union
select owner, index_name, 'INDEX', table_owner, table_name, table_type, null, null
  from all_indexes
union
select p.owner, p.table_name, 'TABLE', f.owner, f.table_name, 'TABLE', null, null
  from all_constraints p
  join all_constraints f 
    on  F.R_CONSTRAINT_NAME = P.CONSTRAINT_NAME 
    and F.CONSTRAINT_TYPE = 'R'
    and p.constraint_type='P'
;
/

EDIT

I have tried do concate all dependencies by using this function:

create 
 or replace
function dependency(
   i_name varchar2
  ,i_type varchar2
  ,i_owner varchar2
  ,i_level number := 0
  ,i_token clob := ' ') return clob
is
  l_token clob := i_token;
  l_exist number := 0;
begin
  select count(*) into l_exist 
    from all_objects
    where   object_name  = i_name
      and   object_type  = i_type
      and   owner = i_owner;  

  if l_exist > 0 then
    l_token := l_token || ';' || i_level || ';' || 
      i_name  || ':' || i_type || ':' || i_owner;
  else
    -- if not exist function recursion is finished
    return l_token;
  end if;

  for tupl in (
    select distinct
       referenced_name
      ,referenced_type
      ,referenced_owner
      from REALLY_ALL_DEPENDENCIES 
      where name  = i_name
      and   type  = i_type
      and   owner = i_owner
    )
  loop
   -- if cyclic dependency stop and shout!
    if i_token like '%' || tupl.referenced_name || ':' || tupl.referenced_type || ':' || tupl.referenced_owner || '%' then
      select count(*) into l_exist 
        from REALLY_ALL_DEPENDENCIES
        where   name  = tupl.referenced_name 
          and   type  = tupl.referenced_type 
          and   owner =  tupl.referenced_owner;  
      if  l_exist > 0 then
        return '!!!CYCLIC!!! (' || i_level || ';' || tupl.referenced_name || ':' || tupl.referenced_type || ':' || tupl.referenced_owner || '):' || l_token;
      end if;
    end if;

    -- go into recursion
    l_token := dependency(
       tupl.referenced_name
      ,tupl.referenced_type
      ,i_owner /* I just want my own sources */
      ,i_level +1
      ,l_token);
  end loop;

  -- no cyclic condition and loop is finished
  return l_token;
end;
/

And I can query through

select
   object_name
  ,object_type
  ,owner
  ,to_char(dependency(object_name, object_type, owner)) as dependecy
  from all_objects 
  where owner = 'SYSTEM'
;

Ok, maybe it is something like "cheating" but you can not do cyclic dependencies at creation time. So at least as a human beeing I am only able to create one object after another :-) And this sequence should be "reverse engineer able".

Now I am more interested in a solution than before ;-) And it is still about the tricky part ... "How can I select all soures from a schema orderd by its installation sequence (dependent objects list prior the using object)"? It is just some kind of sorting problem, insn't it?

+3  A: 

Usually you "cheat" by creating the objects in a particular order. For example, you might make sequences first (they have zero dependencies). Then you might do tables. After that, package specs, then package bodies, and so on.

Keep in mind that it is possible to have cyclic dependencies between packages, so there are cases where it will be impossible to satisfy all dependencies at creation anyway.

What's the business case here? Is there a real "problem" or just an exercise?

EDIT

The export tool we use exports objects in the following order:

  • Database Links
  • Sequences
  • Types
  • Tables
  • Views
  • Primary Keys
  • Indexes
  • Foreign Keys
  • Constraints
  • Triggers
  • Materialized Views
  • Materialized View Logs
  • Package Specs
  • Package Bodies
  • Procedures
  • Functions

At the end, we run the dbms_utility.compile_schema procedure to make sure everything is valid and no dependencies are missed. If you use other object types than these, I'm not sure where they'd go in this sequence.

Adam Hawkes
One thing to do is create views with the FORCE option, so the view definition is saved even if a functional dependency is missing.
Adam Musch
Some of our views call packaged functions so we first compile package specs then views and then package bodies
Rene
I would say some kind of both :-) In fact I am currently working in an open source project where we do a lot in oracle. The problem is when someone has corrupted his database and want to start from a fresh installation. Then you have to download from svn a bunch (>100) of sql sources. It is not comfortable to install them manually, so I want to write some install.sql where people do not have to care about insallation sequence. Maybe there is a better way then I thought about -> getting the dependecies?
christian