【发布时间】:2015-05-19 20:13:39
【问题描述】:
我正在尝试在 pl/sql 中编写一个过程,它将告诉我谁对 Oracle 数据库中的所有应用程序表具有 SELECT、INSERT、UPDATE、DELETE 权限。
要么:
- 用户对表没有权限
- 用户基于直接授权(如“将 table_ABC 上的选择授予 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 完成相同的操作
如果有系统权限授予,variable3 = 'TRUE' 或使用 SELECT INTO 完成相同的操作
如果有 DBA 角色授权,variable4 = '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;
【问题讨论】: