我正在尝试在pl / sql中编写一个过程,它将告诉我谁对Oracle数据库中的所有应用程序表具有SELECT,INSERT,UPDATE,DELETE权限 .
或者:
-
用户对表没有任何权限
-
用户具有基于直接授权的表的权限,如"grant select on table_ABC to user_123"
-
用户具有基于授权角色的表的权限,如"grant read_only_role to user_123",其中read_only_role包含"grant select on table_ABC to read_only_role"
-
用户基于SELECT ANY TABLE等系统特权对表具有特权
-
用户基于DBA等包含SELECT ANY TABLE的角色对表具有特权 .
现在,当我对用户或表名进行硬编码时,我没有遇到使用#2(例如)创建过程的错误 . 但是当我尝试创建包含所有这些场景的1个过程时,我在DATA_NOT_FOUND时遇到了问题 .
我可以处理异常,但程序随后退出 . 无论是否找到数据,我都无法运行代码 . SQL%NOTFOUND对我不起作用,因为在执行SQL%NOTFOUND的代码之前引发了DATA_NOT_FOUND异常 .
我想要发生的是:
-
该过程循环遍历所有应用程序表
-
该过程循环遍历所有用户
-
如果存在直接授权,则variable1 ='TRUE'或使用SELECT INTO完成相同的操作
-
如果存在角色授权,则variable2 ='TRUE'或使用SELECT INTO完成相同的操作
-
如果有系统权限授予,变量3 ='TRUE'或使用SELECT INTO完成同样的事情
-
如果有DBA角色授权,变量4 ='TRUE'或使用SELECT INTO完成同样的事情
-
该过程为上面的每个项目打印表名,用户名,是/否 .
如何修改代码,以便如果User_123对Table_ABC具有SELECT权限,则variable1 ='TRUE',否则variable1 ='FALSE'?如果dba_tab_privs中没有User_123的记录,则不应引发DATA_NOT_FOUND异常 .
非常感谢你提前 .
DECLARE
by_tab_priv varchar(20);
BEGIN
dbms_output.enable(1000000);
FOR x IN ( SELECT table_name
FROM dba_tables
WHERE owner IN ('NIKUP')
ORDER BY table_name )
LOOP
BEGIN
FOR y IN ( SELECT username from dba_users
ORDER BY username)
LOOP
SELECT grantee
INTO by_tab_priv
FROM dba_tab_privs
WHERE grantee=y.username
and table_name=x.table_name
and privilege in ('SELECT')
MINUS
SELECT granted_role
FROM dba_role_privs
WHERE granted_role in (
SELECT grantee
FROM dba_tab_privs
WHERE grantee=y.username
and table_name=x.table_name
and privilege in ('SELECT'));
BEGIN
dbms_output.put_line(y.username || ' ' || by_tab_priv);
END;
END LOOP;
END;
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
by_tab_priv:='FALSE';
END;
2 回答
使用以下技巧来避免异常
或者你可以使用
SIGN(COUNT(grantee))
,它返回1
或0
像这样的东西:
结束;
UPDATE
异常仅链接到循环内的块,它不是全局异常
块具有如下结构:
并且你可以在一个函数中有多个块,每个块都可以自己处理异常 .