首页 > 数据库 >SQL Server递归查询

SQL Server递归查询

时间:2023-02-27 12:02:41浏览次数:43  
标签:name 递归 menu pid Server rbac SQL id select

本示例仅适用于SQL Server 2005及以上版本

1.语法结构

语法结构基本上与PostgreSql的一致,不同之处在于with后面直接跟临时表表名,且内部使用"union all"连接。

with 临时表名称 as (
A.初始条件语句(非递归部分)

union all

B.递归部分语句
) [SELECT | INSERT | UPDATE | DELETE]

1.1 说明

  1. 前半部分A为初始条件语句,后半部分B为要进行的递归语句
  2. 先执行A语句,然后将A语句的结果作为B语句的条件,使用union all进行连接

2.示例

2.1 表结构

创建表信息

-- ----------------------------
-- Table structure for rbac_menu
-- ----------------------------
IF EXISTS (SELECT * FROM sys.all_objects WHERE object_id = OBJECT_ID(N'[rbac_menu]') AND type IN ('U'))
DROP TABLE [rbac_menu]
GO

CREATE TABLE [rbac_menu] (
[id] bigint NOT NULL,
[pid] bigint NULL,
[menu_name] nvarchar(255) COLLATE Chinese_PRC_CI_AS NULL
)
GO

ALTER TABLE [rbac_menu] SET (LOCK_ESCALATION = TABLE)
GO

EXEC sp_addextendedproperty
'MS_Description', N'ID',
'SCHEMA', N'dbo',
'TABLE', N'rbac_menu',
'COLUMN', N'id'
GO

EXEC sp_addextendedproperty
'MS_Description', N'父ID',
'SCHEMA', N'dbo',
'TABLE', N'rbac_menu',
'COLUMN', N'pid'
GO

EXEC sp_addextendedproperty
'MS_Description', N'菜单名称',
'SCHEMA', N'dbo',
'TABLE', N'rbac_menu',
'COLUMN', N'menu_name'
GO

-- ----------------------------
-- Records of rbac_menu
-- ----------------------------
INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N'100101', N'1001', N'权限管理')
GO

INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N'10010101', N'100101', N'菜单管理')
GO

INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N'10010102', N'100101', N'用户管理')
GO

INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N'10010103', N'100101', N'角色管理')
GO

INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N'1001010101', N'10010101', N'设置角色')
GO

INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N'1001010102', N'10010101', N'设置用户')
GO

INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N'1001010301', N'10010103', N'查看')
GO

INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N'1001010302', N'10010103', N'新增')
GO

INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N'1001010303', N'10010103', N'修改')
GO

INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N'1001010304', N'10010103', N'删除')
GO

-- ----------------------------
-- Primary Key structure for table rbac_menu
-- ----------------------------
ALTER TABLE [rbac_menu] ADD CONSTRAINT [rbac_menu_pkey] PRIMARY KEY CLUSTERED ([id])
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY]
GO

查询表数据

select * from rbac_menu;

查询结果

SQL Server递归查询_递归

2.2 获取所有子节点信息

with temp_table as (
-- 初始语句,仅执行一次
select "id", pid, "menu_name" from rbac_menu where pid = 1001

-- 使用union连接结果集(去重,不去重请使用"union all")
union all

-- 递归语句
select a."id", a.pid, a."menu_name" from rbac_menu a,temp_table b where a.pid = b."id"
)
select * from temp_table order by pid, "id";

查询结果

SQL Server递归查询_子节点_02

2.3 获取所有子节点信息(控制递归层数)

with temp_table as (
-- 初始语句,仅执行一次,设置一个变量 number=1
select
1 number, "id", pid, "menu_name"
from
rbac_menu
where
pid = 1001

-- 使用union连接结果集(去重,不去重请使用"union all")
union all

-- 递归语句,执行number次,控制number,即可控制递归的层次
select
(number+1) as n, a."id", a.pid, a."menu_name"
from
rbac_menu a,temp_table b
where
a.pid = b."id"
and number < 2 -- 递归2层
) select * from temp_table
order by pid, "id";

查询结果

SQL Server递归查询_条件语句_03

2.4 获取所有父节点信息

with temp_table as (
select "id", pid, "menu_name" from rbac_menu where "id" = 1001010302

union all

select a."id", a.pid, a."menu_name" from rbac_menu a,temp_table b where a.id = b.pid
)
select * from temp_table order by pid desc, "id" desc;

查询结果

SQL Server递归查询_子节点_04

2.5 任意节点获取所有父节点及子节点信息(包括自身)

with temp_table as (
select "id", pid, "menu_name" from rbac_menu where "id" = 10010103
union all
select a."id", a.pid, a."menu_name" from rbac_menu a,temp_table b where a."id" = b.pid
), temp_table_b as (
select "id", pid, "menu_name" from rbac_menu where pid = 10010103
union all
select a."id", a.pid, a."menu_name" from rbac_menu a,temp_table_b b where a.pid = b."id"
)
select * from temp_table
union
select * from temp_table_b order by pid, "id";

查询结果

SQL Server递归查询_递归_05

标签:name,递归,menu,pid,Server,rbac,SQL,id,select
From: https://blog.51cto.com/abcd/6087235

相关文章

  • 通过EXCEL/WPS文件,拼接SQL,刷数据库数据
    WPS如何把日期变成文本格式?【快捷选择同一列多条记录】同一列,鼠标左键标记A,SHIFT+鼠标左键标记B,等于选择A-B的之间的数据【向下填充】在第一行输入数据,选择同一列A-B......
  • docker安装mysql
    查看mysql镜像版本https://registry.hub.docker.com/_/mysql/tags指定版本号下载sudodockerpullmysql:5.7......
  • MySQL报错:ERROR 1290 (HY000): The MySQL server is running with the --secure-file-
     MySQL报错:ERROR1290(HY000):TheMySQLserverisrunningwiththe--secure-file-privoptionsoitcannotexecutethisstatement 测试使用“select...into......
  • MySQL主从复制报错:Fatal error: The slave I/O thread stops because master and slav
    报错信息:Fatalerror:TheslaveI/OthreadstopsbecausemasterandslavehaveequalMySQLserverUUIDs;theseUUIDsmustbedifferentforreplicationtowork......
  • mysql事务
    事务的acid特性原子性隔离性 一致性 持久性事务的状态 活动的 部分提交的 提交的 失败的 终止显示事务和隐式事务SHOWVARIABLESlike'autocommit'链式......
  • SQL Server CONVERT() 函数
    定义和用法CONVERT()函数是把日期转换为新数据类型的通用函数。CONVERT()函数可以用不同的格式显示日期/时间数据。语法CONVERT(data_type(length),data_to_be_conve......
  • SQL行转列、列转行(SQL Server版)
    在SQLServer中使用SQL实现行转列、列转行,可以使用多种方法,在SQL2005以前可以使用casewhenthen...语句,但这种方法的问题在于列举的列名要写死,如果列名很多,casewhen语......
  • Mysql 自定义目录安装
    这里教大家安装Mysql的时候自定义安装目录1、Mysql版本我这里选择的是8.0,下边有下载链接,其他的版本也行,操作都是一样的 Mysql8.0下载链接:MySQL::DownloadMySQLInsta......
  • 图解 SQL 的执行顺序,优雅
     SQL是一个声明式语言一个完整的SQL语句会告诉MySqlserver要从那些表中查数据【得到数据集】,对得到的数据集按什么条件进行筛选【where】,按什么规则进行分组、计算......
  • .Net6 微服务之Ocelot+IdentityServer4入门看这篇就够了
    前言.Net6使用Consul实现服务注册与发现看这篇就够了.Net6使用Ocelot+Consul看这篇就够了.Net6微服务之Polly入门看这篇就够了书接上文,本文将继续建立在.N......