0

我需要查询一个Oracle数据库并取回哪些权限被授予哪些角色和哪些对象。因为我将根据我正在创建的数据库管理系统中的配置撤销或授予对象角色的权限。

当我遍历要处理的对象时,我需要知道角色是否已被授予对该对象的任何特权。这需要在排队GRANT或执行之前REVOKE完成。

ODP.NET提供程序不支持运行多个 Oracle 语句,它们必须一个接一个地运行或封装在一个BEGIN END块中(然后算作单个语句)。有些语句甚至必须放在EXECUTE IMMEDIATE块内的语句中才能工作。

我知道您可以多次将对象上的相同权限授予角色而不会破坏任何内容,但是(如果我错了,请纠正我)从角色上撤消该角色没有的对象上的权限会引发异常和中断整个块的执行。

在对 Oracle 数据库执行任何操作之前,我首先查询完成工作所需的所有信息,因为我发现这对于性能而言是最好的,而不是通过查询每个对象、角色或权限来与服务器打乒乓球...

然后,在处理 Oracle 数据库时,我将刚刚查询的本地信息与配置的信息进行比较,并据此执行不同的操作。

我使用 SQLTracker 并找到 Toad 使用此查询查找授予角色对象的权限并删除角色 where 子句

SELECT dtp.PRIVILEGE,
       dtp.grantable ADMIN,
       dtp.grantee,
       dtp.grantor,
       dbo.owner,
       dbo.object_type,
       dbo.object_name,
       dbo.status,
       '' column_name
  FROM ALL_TAB_PRIVS dtp, DBA_OBJECTS dbo
 WHERE dtp.TABLE_SCHEMA = dbo.owner AND dtp.table_name = dbo.object_name
       AND dbo.object_type IN
              ('TABLE',
               'VIEW',
               'PACKAGE',
               'PROCEDURE',
               'FUNCTION')
UNION ALL
SELECT dcp.PRIVILEGE,
       dcp.grantable ADMIN,
       dcp.grantee,
       dcp.grantor,
       dbo.owner,
       dbo.object_type,
       dbo.object_name,
       dbo.status,
       dcp.column_name
  FROM ALL_COL_PRIVS dcp, DBA_OBJECTS dbo
 WHERE dcp.TABLE_SCHEMA = dbo.owner AND dcp.table_name = dbo.object_name
       AND dbo.object_type IN
              ('TABLE',
               'VIEW',
               'PACKAGE',
               'PROCEDURE',
               'FUNCTION');

我认为此查询将为我提供所需的信息,但如果使用具有大量对象的非常大的 Oracle 数据库,我担心会出现性能问题。

问:查询 Oracle 数据库上哪些对象的哪些角色授予哪些权限的最佳方法是什么?

我发布的查询只是我自己的建议之一,但由于我在这里提出这个问题,我显然对此不确定,并希望对查询进行一些输入。

我在正确的轨道上吗?是否需要修改?我应该废弃它并使用完全不同的方法吗?

4

2 回答 2

1

好吧,没有实际检索数据就无法检索数据,因此您必须查询表。如果您的问题是撤销不存在的权限,您可以为其编写一个函数。像这样的东西

create or replace procedure revoke_priv (
    object_owner    all_objects.owner%type , 
    object_name     all_objects.object_name%type , 
    privilege       all_tab_privs.privilege%type , 
    role_name       role_tab_privs.role%type)
authid current_user
as
    err number;
    stmt varchar2(4001);
begin
    stmt := 'revoke ' || privilege || ' on ' || object_owner || '.' || object_name ||' from ' || role_name;
    execute immediate stmt;
exception when others then 
    err := SQLCODE;
    if (err = -1927) then
        dbms_output.put_line('the privilege does not exists for the role');
    else
        raise;
    end if;
end;
/

这就是场景

SQL>create role my_role;

Role created.

SQL>grant select on scott.dept to my_role;

Grant succeeded.

SQL>select role , owner , table_name , PRIVILEGE from role_tab_privs where role = 'MY_ROLE';

ROLE                           OWNER                          TABLE_NAME                     PRIVILEGE
------------------------------ ------------------------------ ------------------------------ ----------------------------------------
MY_ROLE                        SCOTT                          DEPT                           SELECT

SQL>revoke select on scott.dept from my_role;

Revoke succeeded.

SQL>revoke select on scott.dept from my_role;
revoke select on scott.dept from my_role
*
ERROR at line 1:
ORA-01927: cannot REVOKE privileges you did not grant

SQL>grant select on scott.dept to my_role;

Grant succeeded.

SQL>exec revoke_priv('SCOTT','DEPT','SELECT','MY_ROLE');

PL/SQL procedure successfully completed.

SQL>select role , owner , table_name , PRIVILEGE from role_tab_privs where role = 'MY_ROLE';

no rows selected

SQL>exec revoke_priv('SCOTT','DEPT','SELECT','MY_ROLE');
the privilege does not exists for the role

PL/SQL procedure successfully completed.

SQL>drop role my_role;

Role dropped.
于 2013-06-13T12:42:47.637 回答
1

我最终使用了问题中提供的查询,它似乎工作正常。我需要的所有信息都在那里。

我最终ALL从没有重复的结果中删除了部分,UNION ALL给了我一个较小的结果集。

SELECT dtp.PRIVILEGE,
       dtp.grantable ADMIN,
       dtp.grantee,
       dtp.grantor,
       dbo.owner,
       dbo.object_type,
       dbo.object_name,
       dbo.status,
       '' column_name
  FROM ALL_TAB_PRIVS dtp, DBA_OBJECTS dbo
 WHERE dtp.TABLE_SCHEMA = dbo.owner AND dtp.table_name = dbo.object_name
       AND dbo.object_type IN
              ('TABLE',
               'VIEW',
               'PACKAGE',
               'PROCEDURE',
               'FUNCTION')
UNION
SELECT dcp.PRIVILEGE,
       dcp.grantable ADMIN,
       dcp.grantee,
       dcp.grantor,
       dbo.owner,
       dbo.object_type,
       dbo.object_name,
       dbo.status,
       dcp.column_name
  FROM ALL_COL_PRIVS dcp, DBA_OBJECTS dbo
 WHERE dcp.TABLE_SCHEMA = dbo.owner AND dcp.table_name = dbo.object_name
       AND dbo.object_type IN
              ('TABLE',
               'VIEW',
               'PACKAGE',
               'PROCEDURE',
               'FUNCTION');

查询可能非常昂贵,具体取决于查询的数据库大小,因此建议只查询一次或使用更多 where 子句来缩小结果集。

于 2013-06-20T13:05:39.120 回答