2010-03-18 20 views
0

我在Oracle pl/sql上有一个分层表。是这样的:更改和更新层次关系表以查看是否有任何子项的过程

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

我需要创建一个过程来改变该表,所以我得到一个新的领域,它告诉,对每个节点,如果有任何子女或没有。

是否可以在一个过程中进行修改和更新?任何代码示例将不胜感激。

感谢

回答

2

你不能做的ALTER TABLEDDL),并在一个单一的步骤UPDATEDML)。

您将必须执行ALTER TABLE,然后是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; 

,虽然在此之前三思而后行。如果id有任何带有查询的孩子,您现在可以轻松找出答案。

这一次会给你比如所有顶级节点的子数:

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 

添加具有冗余数据的额外的列将改变你的数据更加困难,因为你将永远有更新当添加/删除孩子时,父母也是如此。

+0

表中的数据不会经常更改。事实上,它可能永远不会改变。有关该查询的问题是,如果我举例说明所有根节点,并且我想知道每个节点是否有子节点,那么我将不得不按照与根节点数量相同的次数执行查询。 是不是可以使用类似的东西: 立即执行'alter table'... 在一个单一的步骤? – user295744 2010-03-18 14:51:46

+0

@ tr-raziel:编辑我的答案以解释如何使用'EXECUTE IMMEDIATE'工作,但我还添加了一个查询,该查询应该为您提供所有根节点的正确计数。 – 2010-03-18 15:02:20

+0

非常感谢。我明白你现在想说什么。 – user295744 2010-03-18 15:09:42

0

如果你只是需要知道孩子是否存在,下面的查询可以做到没有循环或非规格化列。

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在行有孩子时返回0,如果没有孩子则返回1。

我想你可能通过巧妙地使用分析函数和LEVEL伪列来得到确切数量的孩子,但我不确定。

相关问题