在sql板块贴了一贴关于现在所做的权限模块,在编辑上级群组时,如何处理下级群组继承权限的帖子.
1.
请教一个树状关系的删除操作
有两个表
table1 (群组)
g_ id parent_id
1 0
2 0
3 1
.........
如上的 父子关系
table2 (群组对应 权限)
g_id mp_code
1 a
1 b
2 a
3 b
.....就是table1 中的g_id 对权限表的一对多关系
原来的操作是,只有 父群组 有的权限 那么子群组就可以继承下来,
如 table2中 群组 2和3 都是在父群组 1所拥有的权限 a, b 前提下
继承,而 群组 3如果有子群组的话也只能拥有权限a或没有
现在出现一个问题,如果我编辑了 群组1的权限,此时可能新增也有
可能删除了某权限,比如现在 群组1的权限 为 a 和 c 那么按道理,我就
必须删除掉 群组3所有的b权限,因为 他的父群组 1已没有了 b这个权限。
不知道这个语句则怎么写,
我原来写一个 ,很没效率
delete * from table2 where mp_code in(
select id from t_sys_group_detail
connect by prior id = parent_id
start with parent_id = 1
)
minus
(
select mp_code from t_sys_group_power where g_id = 1
)
)
and g_id in
(
select id from table1
connect by prior id = parent_id
start with parent_id = 1
)
大意就是:删除 父群组没有而子群组却有的 权限
有两个表
table1 (群组)
g_ id parent_id
1 0
2 0
3 1
.........
如上的 父子关系
table2 (群组对应 权限)
g_id mp_code
1 a
1 b
2 a
3 b
.....就是table1 中的g_id 对权限表的一对多关系
原来的操作是,只有 父群组 有的权限 那么子群组就可以继承下来,
如 table2中 群组 2和3 都是在父群组 1所拥有的权限 a, b 前提下
继承,而 群组 3如果有子群组的话也只能拥有权限a或没有
现在出现一个问题,如果我编辑了 群组1的权限,此时可能新增也有
可能删除了某权限,比如现在 群组1的权限 为 a 和 c 那么按道理,我就
必须删除掉 群组3所有的b权限,因为 他的父群组 1已没有了 b这个权限。
不知道这个语句则怎么写,
我原来写一个 ,很没效率
delete * from table2 where mp_code in(
select id from t_sys_group_detail
connect by prior id = parent_id
start with parent_id = 1
)
minus
(
select mp_code from t_sys_group_power where g_id = 1
)
)
and g_id in
(
select id from table1
connect by prior id = parent_id
start with parent_id = 1
)
大意就是:删除 父群组没有而子群组却有的 权限
这个结构一直遭到批判,只是设计落到自己身上,只能将就原来的表结构进行设计.
这种结构在精神上比较接近显示的 管理概念, 就是 那种上级管理下级,下级管理下下级......
(另有一种设计思路是:所有的群组都和模块挂钩,只是存在一个是否可操作的概念, 表的设计时一个
多对多的对应关系, 一个群组对于多个模块,一个模块对应多个群组,看群组是否有此模块的权限,就是看它们的关系,一般用1 和 0 来表示, 这中结构是同事比较推崇的,应该他以前设计就是按找这种设计来做的. 思路清晰,执行简单,我也觉得很不错.唯一缺点就是占空简多,一百个人十个模块就要,一千条记录,而用递规树最多就是这个数量.)
人家答复:
1. 感觉上这种东东没有必要强求用一条语句来解决问题。可以用一个功能函数或过程来实现这样的业务逻辑。 2. 出现这么麻烦的问题,一定是权限管理逻辑有问题,考虑从逻辑上处理,比删除要有效的多。
看来这种问题除了比较有心的人,是很懒的去看的,感觉也挺繁琐的,没法企业要求如此做,只能顺着上帝的意思了.
显示形式用的是左右,左边是树状的导航条,或是群组触发条,右边就是群组的具体内容了.
左边的树状用的是一个递规的pl/sql 效率很低,多了慢的有点受不了.
不过上级应该不是很多, 因为到最好能用这个的只有寥寥几个管理员.
在这个设计中,除了操作界面,花了很多心思,其它东西都是很普通的那种.
群组有三个可操作区域,可操作部门,可操作物料种类也是用的这种结构,另外一个人干脆把这些东西都让我一个人做了. 因为 递归 条件, 选择 sql语句长的有时 赶上 我做的作文了,又臭又长,不过还是要硬着头皮写下来. 写多了几次, 好像挺有满足感的,就是控制台异常老被我整个很长,一句一句调试,能不长才怪.
比较严重问题出来,群组编辑这边,因为原来的树状关系,有一个很重要的地方是,
子群组的权限能力,在父群组中选择,也就是父有子可能有,也可能没有. 一对多的新增操作方法一般是.删除原一对多关系,重新添加一对多的. 问题就在这,如果原上级群组删除了一个已被子群组继承的权限,那么控制就会出现问题,子权力大于父群组了. 开始一直考虑用一条语句搞定,想了很久一直没有办法. 只好写了一个过程.
create or replace procedure group_delete(
in_g_id in t_sys_group_detail.id%type -- 已被更新的群组做为父群组传入
)
as
V_group_power_id t_sys_group_power.id%type;
V_group_power_code t_sys_group_power.mp_code%type;
V_count int :=0;
cursor group_cursor is
select gp.id,gp.mp_code from t_sys_group_power gp
where exists(
select id from(
select id from t_sys_group_detail gd
where gd.is_delete = 0
connect by prior id = parent_id
start with parent_id = in_g_id
) tmp_g
where gp.g_id = tmp_g.id
);
BEGIN
open group_cursor;
loop
fetch group_cursor into V_group_power_id,V_group_power_code;
exit when group_cursor%notfound;
V_count := 0;
select count(*) into V_count from t_sys_group_power gp
where gp.g_id = in_g_id and gp.mp_code = V_group_power_code;
/**检测当前的下级群组所有的权限是否上级仍旧存在,如果不存在则删除之**/
if V_count <= 0 then
delete from t_sys_group_power gp where gp.id = V_group_power_id;
end if;
end loop;
close group_cursor;
commit;
END;
in_g_id in t_sys_group_detail.id%type -- 已被更新的群组做为父群组传入
)
as
V_group_power_id t_sys_group_power.id%type;
V_group_power_code t_sys_group_power.mp_code%type;
V_count int :=0;
cursor group_cursor is
select gp.id,gp.mp_code from t_sys_group_power gp
where exists(
select id from(
select id from t_sys_group_detail gd
where gd.is_delete = 0
connect by prior id = parent_id
start with parent_id = in_g_id
) tmp_g
where gp.g_id = tmp_g.id
);
BEGIN
open group_cursor;
loop
fetch group_cursor into V_group_power_id,V_group_power_code;
exit when group_cursor%notfound;
V_count := 0;
select count(*) into V_count from t_sys_group_power gp
where gp.g_id = in_g_id and gp.mp_code = V_group_power_code;
/**检测当前的下级群组所有的权限是否上级仍旧存在,如果不存在则删除之**/
if V_count <= 0 then
delete from t_sys_group_power gp where gp.id = V_group_power_id;
end if;
end loop;
close group_cursor;
commit;
END;
除了练习,这是我第一次这样用. 看上去的确有点多.就我而言.
到目前位置,群组算比较完整了,除了模块这个模块,因为是后台使用的都没有做完全,只是做了添加.