SQL Server递归查询
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL Server递归查询相关的知识,希望对你有一定的参考价值。
本示例仅适用于SQL Server 2005及以上版本
1.语法结构
语法结构基本上与PostgreSql的一致,不同之处在于with后面直接跟临时表表名,且内部使用"union all"连接。
with 临时表名称 as (
A.初始条件语句(非递归部分)
union all
B.递归部分语句
) [SELECT | INSERT | UPDATE | DELETE]
1.1 说明
- 前半部分A为初始条件语句,后半部分B为要进行的递归语句
- 先执行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, NID,
SCHEMA, Ndbo,
TABLE, Nrbac_menu,
COLUMN, Nid
GO
EXEC sp_addextendedproperty
MS_Description, N父ID,
SCHEMA, Ndbo,
TABLE, Nrbac_menu,
COLUMN, Npid
GO
EXEC sp_addextendedproperty
MS_Description, N菜单名称,
SCHEMA, Ndbo,
TABLE, Nrbac_menu,
COLUMN, Nmenu_name
GO
-- ----------------------------
-- Records of rbac_menu
-- ----------------------------
INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N100101, N1001, N权限管理)
GO
INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N10010101, N100101, N菜单管理)
GO
INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N10010102, N100101, N用户管理)
GO
INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N10010103, N100101, N角色管理)
GO
INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N1001010101, N10010101, N设置角色)
GO
INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N1001010102, N10010101, N设置用户)
GO
INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N1001010301, N10010103, N查看)
GO
INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N1001010302, N10010103, N新增)
GO
INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N1001010303, N10010103, N修改)
GO
INSERT INTO [rbac_menu] ([id], [pid], [menu_name]) VALUES (N1001010304, N10010103, 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;
查询结果
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";
查询结果
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";
查询结果
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;
查询结果
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递归查询的主要内容,如果未能解决你的问题,请参考以下文章