Oracle树形查询实战:CONNECT BY双向遍历

CONNECT BY 树形查询实战

📢 适用数据库说明

  • Oracle :原生支持 CONNECT BY 语法,是处理树形数据的标准方案。
  • 达梦数据库(DM)完全兼容 Oracle 的 CONNECT BY 语法,可直接使用本文所有示例。
  • MySQL / PostgreSQL :不支持 CONNECT BY,请使用 WITH RECURSIVE(公共表表达式)实现类似功能。

📑 目录

  • 一、场景说明
  • [二、核心 SQL 实战](#二、核心 SQL 实战)
    • [1. 父→子向下遍历(查所有子节点)](#1. 父→子向下遍历(查所有子节点))
    • [2. 子→父向上遍历(查所有父节点)](#2. 子→父向上遍历(查所有父节点))
  • 三、关键语法对比
  • 四、避坑要点
  • [五、Java 调用示例(MyBatis)](#五、Java 调用示例(MyBatis))
  • 六、总结

一、场景说明

处理菜单 / 组织架构等树形数据时,Oracle CONNECT BY 可实现向上、向下两种递归遍历,无需复杂存储过程。

二、核心 SQL 实战

1. 父→子向下遍历(查所有子节点)

sql 复制代码
select distinct
    m.menu_id,
    m.parent_id,
    m1.menu_name as parent_name,
    m.menu_name,
    m.menu_abbreviation,
    m.display_location,
    m.path,
    m.icon,
    m.order_num,
    m.menu_type,
    m.is_frame
from auth_sys_menu m
left join auth_sys_menu m1 on m.parent_id = m1.menu_id
start with m.menu_id in ('13')---这里填父级菜单
connect by prior m.menu_id = m.parent_id
order by m.parent_id, m.order_num;

效果返回指定父节点下所有子菜单(含多级后代),用于菜单批量授权、树形展开。

2. 子→父向上遍历(查所有父节点)

sql 复制代码
select distinct
    m.menu_id,
    m.parent_id,
    m1.menu_name as parent_name,
    m.menu_name,
    m.menu_abbreviation,
    m.display_location,
    m.path,
    m.icon,
    m.order_num,
    m.menu_type,
    m.is_frame
from auth_sys_menu m
left join auth_sys_menu m1 on m.parent_id = m1.menu_id
start with m.menu_id in ('1024')----这里填写子菜单
connect by prior m.parent_id = m.menu_id
order by m.parent_id, m.order_num;

效果返回指定子节点的所有上级节点(含根节点),用于面包屑导航、权限继承校验。## 三、关键语法对比

遍历方向 CONNECT BY 条件 核心作用
父→子 PRIOR m.menu_id = m.parent_id 查所有后代节点
子→父 PRIOR m.parent_id = m.menu_id 查所有祖先节点

四、避坑要点

  • DISTINCT:层级查询易出现重复数据,需去重。
  • START WITH:支持 IN 传入多个起始节点,实现多分支遍历。
  • ORDER BY:配合 order_num 保证菜单展示顺序。

五、Java 调用示例(MyBatis)

xml 复制代码
<select id="listChildMenus" resultType="com.xxx.vo.MenuVO">
    select distinct
        m.menu_id,
        m.parent_id,
        m1.menu_name as parent_name,
        m.menu_name,
        m.path,
        m.icon
    from auth_sys_menu m
    left join auth_sys_menu m1 on m.parent_id = m1.menu_id
    start with m.menu_id in (#{menuId})
    connect by prior m.menu_id = m.parent_id
    order by m.parent_id, m.order_num
</select>

六、总结

CONNECT BY 是 Oracle 处理树形数据的高效方案,掌握两种遍历方式可覆盖大部分业务场景。通过调整 PRIOR 的位置,即可轻松实现向上、向下两种遍历,覆盖绝大多数菜单、组织架构等业务场景。


相关推荐
小菜同学爱学习19 天前
第一章 初识达梦数据库:基础认知与环境准备
数据库·达梦
Navicat中国1 个月前
Navicat 企业版数据传输是否支持达梦 → OceanBase迁移?数据迁移报错
数据库·oceanbase·达梦·navicat·数据迁移·数据传输
qq_283720052 个月前
nestjs实战(五):从零搭建NestJS+TypeORM+原生驱动+达梦DM8,两种连接融合
达梦·orm·nest.js·dm·原生
qq_283720052 个月前
nestjs实战(六):诺依Nest.js + MySQL 项目改造为兼容达梦8数据库详细教程
javascript·数据库·mysql·达梦·nest.js·诺依
Amarone2 个月前
DM8 切库实战
达梦·kingbase·dm·神通
cgsthtm3 个月前
Oracle19C部门层级结构视图
oracle19c·递归查询·start with·connect by·piror·层级结构
Lw老王要学习3 个月前
CentOS 7.9达梦数据库安装全流程解析
linux·运维·数据库·centos·达梦
SamRol4 个月前
达梦数据库指令 及 在Spring Boot + MyBatis-Plus上的使用
java·数据库·spring boot·mybatis·达梦·intellij idea
卡布叻_星星4 个月前
基于 SpringBoot(Java17)的后端项目,从连接 MySQL8 数据库改为连接本地的达梦 DM8 数据库
达梦