形结构如何在Oracle中取得树形结构(oracle中取树)

在Oracle数据库中,处理树形结构数据是非常常见的任务,例如组织结构图、部门架构、文件目录等等。而在这些数据中,每个节点有自己的子节点,有时还需要在树状结构中批量查询、修改、删除某个节点及其所有子节点。本文将介绍如何在Oracle中取得树形结构。

一、树形结构的存储

在Oracle中,可以使用两种方式来存储树形结构数据:邻接表和嵌套集模型。邻接表是指在数据表中每一行中保存该节点的父节点ID,通过ID关联到父节点,但是这种方式查找其父级、子级比较麻烦。嵌套集模型则是使用每个节点的左值和右值,左值表示该节点在整个树形结构中出现的位置,右值则表示该节点所有子节点出现的位置,这种方式可以方便的查询节点的层级、父级、子级等信息,但是在修改节点位置时较为复杂,需要重新计算左值和右值。

下面以嵌套集模型为例进行说明。假设有一个部门表:

CREATE TABLE department (
id NUMBER(10),
name VARCHAR2(50),
lft NUMBER(10),
rgt NUMBER(10)
);

其中id表示唯一标识,name是部门名称,lft和rgt是树形结构中每个节点的左值和右值。

二、取得树形结构

1. 查询所有节点

使用下面的语句可以查询出整个树形结构:

SELECT id, name, lft, rgt
FROM department
ORDER BY lft;

结果如下图所示:

![树形结构1](https://img-blog.csdn.net/2018102217332253?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2dhbWluZzMz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/q/70)

2. 查询指定节点及其子节点

如果要查询某个节点及其所有子节点,可以使用以下语句:

SELECT id, name, lft, rgt
FROM department
WHERE lft BETWEEN ? AND ? -- ?是指定节点的左值和右值
ORDER BY lft;

例如,查询id为4的节点及其子节点:

SELECT id, name, lft, rgt
FROM department
WHERE lft BETWEEN 5 AND 10
ORDER BY lft;

结果如下图所示:

![树形结构2](https://img-blog.csdn.net/20181022173432180?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2dhbWluZzMz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/q/70)

3. 查询指定节点的父节点

如果要查询某个节点的父节点,可以使用以下语句:

SELECT id, name, lft, rgt
FROM department
WHERE lft ? -- ?是指定节点的左值和右值
ORDER BY lft DESC
FETCH FIRST 1 ROW ONLY; -- 只查询第一行

例如,查询id为9的节点的父节点:

SELECT id, name, lft, rgt
FROM department
WHERE lft 10
ORDER BY lft DESC
FETCH FIRST 1 ROW ONLY;

结果如下图所示:

![树形结构3](https://img-blog.csdn.net/20181022173619983?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2dhbWluZzMz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/q/70)

4. 添加新节点

添加新节点时,需要确定该节点的左值和右值。假设要在id为2的节点下添加一个名为”研发部”的部门,可以使用以下语句:

DECLARE
lft NUMBER(10);
rgt NUMBER(10);
BEGIN
-- 第一步:为新节点获取左值和右值
SELECT rgt INTO lft FROM department WHERE id = 2;
UPDATE department SET rgt = rgt + 2 WHERE rgt >= lft;
UPDATE department SET lft = lft + 2 WHERE lft > lft;
lft := lft + 1;
rgt := lft + 1;
-- 第二步:插入新节点
INSERT INTO department VALUES (4, '研发部', lft, rgt);
END;

执行完上面的语句后,可以查询出整个树形结构,结果如下图所示:

![树形结构4](https://img-blog.csdn.net/20181022173904119?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2dhbWluZzMz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/q/70)

5. 删除节点

删除节点时,需要注意对应节点的子节点也需要一并删除。假设要删除id为8的节点及其所有子节点,可以使用以下语句:

DECLARE
lft NUMBER(10);
rgt NUMBER(10);
BEGIN
-- 第一步:获取要删除的节点的左值和右值
SELECT lft, rgt INTO lft, rgt FROM department WHERE id = 8;
-- 第二步:删除所有子节点
DELETE FROM department WHERE lft BETWEEN lft AND rgt;
-- 第三步:更新树结构
UPDATE department SET rgt = rgt - (rgt - lft + 1) WHERE rgt > rgt;
UPDATE department SET lft = lft - (rgt - lft + 1) WHERE lft > lft;
END;

执行完上面的语句后,可以查询出整个树形结构,结果如下图所示:

![树形结构5](https://img-blog.csdn.net/20181022174209047?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2dhbWluZzMz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/q/70)

三、结语

本文介绍了在Oracle中如何取得树形结构,包括查询所有节点、查询指定节点及其子节点、查询指定节点的父节点、添加新节点和删除节点等操作。以上内容仅供参考,具体情况需根据实际需求进行修改。


数据运维技术 » 形结构如何在Oracle中取得树形结构(oracle中取树)