Sql 如何处理Oracle分层菜单查询中的权限?
有一个菜单表:Sql 如何处理Oracle分层菜单查询中的权限?,sql,oracle,menu,tree,hierarchical,Sql,Oracle,Menu,Tree,Hierarchical,有一个菜单表: create table MENU ( MENU_ID number(15,0) not null, PARENT_MENU_ID number(15,0), MENU_NAME varchar2(255 char) not null, PERMISSION_ID number(15,0) ) / 和数
create table MENU
(
MENU_ID number(15,0) not null,
PARENT_MENU_ID number(15,0),
MENU_NAME varchar2(255 char) not null,
PERMISSION_ID number(15,0)
)
/
和数据:
INSERT INTO MENU VALUES (20,null,'Menu A',null);
INSERT INTO MENU VALUES (21,null,'Menu B',null);
INSERT INTO MENU VALUES (1001,null,'Menu C',null);
INSERT INTO MENU VALUES (1,1001,'Menu C-A',10);
INSERT INTO MENU VALUES (2,1001,'Menu C-B',34);
INSERT INTO MENU VALUES (3,1001,'Menu C-C',92);
INSERT INTO MENU VALUES (4,1001,'Menu C-D',57);
INSERT INTO MENU VALUES (16,1001,'Menu C-E',22);
INSERT INTO MENU VALUES (1002,1001,'Menu C-F',null);
INSERT INTO MENU VALUES (13,1002,'Menu C-F-A',28);
INSERT INTO MENU VALUES (14,1002,'Menu C-F-B',29);
INSERT INTO MENU VALUES (15,1002,'Menu C-F-C',43);
INSERT INTO MENU VALUES (1003,1001,'Menu C-G',null);
INSERT INTO MENU VALUES (5,1003,'Menu C-G-A',94);
INSERT INTO MENU VALUES (6,1003,'Menu C-G-B',11);
INSERT INTO MENU VALUES (7,1003,'Menu C-G-C',47);
INSERT INTO MENU VALUES (1004,1001,'Menu C-H',null);
INSERT INTO MENU VALUES (8,1004,'Menu C-H-A',120);
INSERT INTO MENU VALUES (9,1004,'Menu C-H-B',41);
INSERT INTO MENU VALUES (10,1004,'Menu C-H-C',52);
INSERT INTO MENU VALUES (11,1004,'Menu C-H-D',40);
INSERT INTO MENU VALUES (12,1004,'Menu C-H-E',39);
INSERT INTO MENU VALUES (2001,null,'Menu D',null);
INSERT INTO MENU VALUES (17,2001,'Menu D-A',14);
INSERT INTO MENU VALUES (18,2001,'Menu D-B',15);
INSERT INTO MENU VALUES (19,2001,'Menu D-C',106);
INSERT INTO MENU VALUES (3001,null,'Menu E',null);
INSERT INTO MENU VALUES (22,3001,'Menu E-A',16);
INSERT INTO MENU VALUES (4001,null,'Menu F',null);
COMMIT;
现在要返回菜单结构,我执行以下操作:
select
level,
PARENT_MENU_ID,
MENU_ID,
SUBSTR(RPAD('-',(level-1),'-')||MENU_NAME,1,20) MENU,
PERMISSION_ID
from
MENU
start with PARENT_MENU_ID is null
connect by prior MENU_ID = PARENT_MENU_ID
/
给予:
LEVEL PARENT_MENU_ID MENU_ID MENU PERMISSION_ID
---------- -------------- ---------- -------------------- -------------
1 20 Menu A
1 21 Menu B
1 1001 Menu C
2 1001 1 -Menu C-A 10
2 1001 2 -Menu C-B 34
2 1001 3 -Menu C-C 92
2 1001 4 -Menu C-D 57
2 1001 16 -Menu C-E 22
2 1001 1002 -Menu C-F
3 1002 13 --Menu C-F-A 28
3 1002 14 --Menu C-F-B 29
3 1002 15 --Menu C-F-C 43
2 1001 1003 -Menu C-G
3 1003 5 --Menu C-G-A 94
3 1003 6 --Menu C-G-B 11
3 1003 7 --Menu C-G-C 47
2 1001 1004 -Menu C-H
3 1004 8 --Menu C-H-A 120
3 1004 9 --Menu C-H-B 41
3 1004 10 --Menu C-H-C 52
3 1004 11 --Menu C-H-D 40
3 1004 12 --Menu C-H-E 39
1 2001 Menu D
2 2001 17 -Menu D-A 14
2 2001 18 -Menu D-B 15
2 2001 19 -Menu D-C 106
1 3001 Menu E
2 3001 22 -Menu E-A 16
1 4001 Menu F
LEVEL PARENT_MENU_ID MENU_ID MENU PERMISSION_ID
---------- -------------- ---------- -------------------- -------------
1 20 Menu A
1 21 Menu B
1 1001 Menu C
2 1001 1 -Menu C-A 10
1 2001 Menu D
2 2001 17 -Menu D-A 14
2 2001 18 -Menu D-B 15
1 3001 Menu E
1 4001 Menu F
这是最简单的部分。现在是保安室。如果我只想在10,11,14和15的许可下查看所有菜单,那么我可以:
select
level,
PARENT_MENU_ID,
MENU_ID,
SUBSTR(RPAD('-',(level-1),'-')||MENU_NAME,1,20) MENU,
PERMISSION_ID
from
MENU
start with PARENT_MENU_ID is null
connect by prior MENU_ID = PARENT_MENU_ID
and PERMISSION_ID in (10,11,14,15)
/
给予:
LEVEL PARENT_MENU_ID MENU_ID MENU PERMISSION_ID
---------- -------------- ---------- -------------------- -------------
1 20 Menu A
1 21 Menu B
1 1001 Menu C
2 1001 1 -Menu C-A 10
2 1001 2 -Menu C-B 34
2 1001 3 -Menu C-C 92
2 1001 4 -Menu C-D 57
2 1001 16 -Menu C-E 22
2 1001 1002 -Menu C-F
3 1002 13 --Menu C-F-A 28
3 1002 14 --Menu C-F-B 29
3 1002 15 --Menu C-F-C 43
2 1001 1003 -Menu C-G
3 1003 5 --Menu C-G-A 94
3 1003 6 --Menu C-G-B 11
3 1003 7 --Menu C-G-C 47
2 1001 1004 -Menu C-H
3 1004 8 --Menu C-H-A 120
3 1004 9 --Menu C-H-B 41
3 1004 10 --Menu C-H-C 52
3 1004 11 --Menu C-H-D 40
3 1004 12 --Menu C-H-E 39
1 2001 Menu D
2 2001 17 -Menu D-A 14
2 2001 18 -Menu D-B 15
2 2001 19 -Menu D-C 106
1 3001 Menu E
2 3001 22 -Menu E-A 16
1 4001 Menu F
LEVEL PARENT_MENU_ID MENU_ID MENU PERMISSION_ID
---------- -------------- ---------- -------------------- -------------
1 20 Menu A
1 21 Menu B
1 1001 Menu C
2 1001 1 -Menu C-A 10
1 2001 Menu D
2 2001 17 -Menu D-A 14
2 2001 18 -Menu D-B 15
1 3001 Menu E
1 4001 Menu F
但这将删除权限为11的菜单,并包括没有子菜单的父菜单。理想情况下,我希望包含11个菜单和不排除子菜单的父菜单,特别是:
LEVEL PARENT_MENU_ID MENU_ID MENU PERMISSION_ID
---------- -------------- ---------- -------------------- -------------
1 1001 Menu C
2 1001 1 -Menu C-A 10
2 1001 1003 -Menu C-G
3 1003 6 --Menu C-G-B 11
1 2001 Menu D
2 2001 17 -Menu D-A 14
2 2001 18 -Menu D-B 15
如何实现这一点?您只需将树从感兴趣的节点(本例中具有权限10、11、14和15的节点)遍历到其根节点。在问题的前一个版本中,有一个查询是这样做的。如果您正在运行Oracle 11g及更高版本,则可以使用
connectby
或递归公共表表达式:
使用连接方式
:
select distinct
menu_id
, parent_menu_id
, menu_name
, permission_id
from menu m
start with permission_id in (10, 11, 14, 15)
connect by prior parent_menu_id = menu_id
order by nvl(parent_menu_id, menu_id), menu_name
MENU_ID PARENT_MENU_ID MENU_NAME PERMISSION_ID
---------- -------------- -------------------- -------------
1001 Menu C
1 1001 Menu C-A 10
1003 1001 Menu C-G
6 1003 Menu C-G-B 11
2001 Menu D
17 2001 Menu D-A 14
18 2001 Menu D-B 15
递归CTE:
with menus(menu_id, parent_menu_id, menu_name, permission_id, lv) as(
select menu_id, parent_menu_id, menu_name, permission_id, 0
from menu
where permission_id in (10,11,14, 15)
union all
select m.menu_id, m.parent_menu_id, m.menu_name, m.permission_id, lv + 1
from menu m
join menus m2
on (m.menu_id = m2.parent_menu_id)
)
select distinct
parent_menu_id
, menu_id
, menu_name
, permission_id
from menus
order by nvl(parent_menu_id, menu_id), menu_name
PARENT_MENU_ID MENU_ID MENU_NAME PERMISSION_ID
-------------- ---------- -------------------- -------------
1001 Menu C
1001 1 Menu C-A 10
1001 1003 Menu C-G
1003 6 Menu C-G-B 11
2001 Menu D
2001 17 Menu D-A 14
2001 18 Menu D-B 15
菜单A-A:10
是菜单C的子菜单
在您的预期输出中它到底是菜单A的子菜单
?菜单C
是否也应该出现在权限\u id=11
中?谢谢你Nicholas Krasnov,你是对的,在菜单名中键入我试图用名称显示结构的地方,即菜单C应该被称为菜单A,反之亦然-我认为-在时间允许的情况下(当然是现在赶飞机)会更正它。更正数据,使查询显示菜单结构,简化了问题。感谢尼古拉斯·克拉斯诺夫的参与。