views:

43

answers:

2

I have a hierarchical table on Oracle pl/sql. something like:

create table hierarchical (
   id             integer primary key,
   parent_id          references hierarchical ,
   name           varchar(100));

I need to create a procedure to alter that table so I get a new field that tells, for each node, if it has any children or not.

Is it possible to do the alter and the update in one single procedure? Any code samples would be much appreciated.

Thanks

+1  A: 

You can not do the ALTER TABLE (DDL) and the UPDATE (DML) in a single step.

You will have to do the ALTER TABLE, followed by the UPDATE.

BEGIN
  EXECUTE IMMEDIATE 'ALTER TABLE hierarchical ADD child_count INTEGER';
  --
  EXECUTE IMMEDIATE '
  UPDATE hierarchical h
  SET child_count = ( SELECT COUNT(*)
                      FROM hierarchical h2
                      WHERE h2.parent_id = h.id )';
END;

Think twice before doing this though. You can easily find out now if an id has any childs with a query.

This one would give you the child-count of all top-nodes for example:

SELECT h.id, h.name, COUNT(childs.id) child_count
FROM hierarchical h
LEFT JOIN hierarchical childs ON ( childs.parent_id = h.id )
WHERE h.parent_id IS NULL
GROUP BY h.id, h.name

Adding an extra column with redundant data will make changing your data more difficult, as you will always have to update the parent too, when adding/removing childs.

Peter Lang
The data in the table will not change often. In fact its possible it will never change. The problem about that query is that if I get for example all the root nodes and I want to know for each if they have children I will have to do the query the same number of times as the number of root nodes.Isn't it possible to use something like: execute immediate 'alter table '...to do both in a single step?
@tr-raziel: Edited my answer to explain how it works using `EXECUTE IMMEDIATE`, but I also added a query that should give you the correct counts for all root-nodes.
Peter Lang
thank you very much. I understand what you were trying to say now.
You're welcome. Which way did you choose?
Peter Lang
Your way! The problem for me on doing this was the mapping to JPA I would have to do after but I think I won't have that much trouble with it anyway.
A: 

If you just need to know whether children exist, the following query can do it without the loop or the denormalized column.

    select h.*, connect_by_isleaf as No_children_exist
      from hierarchical h
start with parent_id is null
connect by prior id = parent_id; 

CONNECT_BY_LEAF returns 0 if the row has children, 1 if it does not.

I think you could probably get the exact number of children through a clever use of analytic functions and the LEVEL pseudo-column, but I'm not sure.

Allan