Oracle - 查询哪些权限授予哪些对象的角色

时间:2013-06-13 11:13:56

标签: .net database oracle query-optimization

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

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

ODP.NET 提供程序不支持运行多个Oracle语句, 它们必须逐个运行或封装在BEGIN END块中(然后计为单个语句)。有些陈述甚至必须放在块内的EXECUTE IMMEDIATE语句中才能生效。

我知道你可以多次向一个角色授予一个对象相同的权限而不会破坏任何东西,但是(如果我错了,请纠正我)从角色没有的角色上撤消角色权限会引发异常并打破整个块的执行。

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

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

我使用SQLTracker并发现Toad使用此查询来查找为角色的对象授予的权限并删除了where 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数据库中哪些对象的哪些权限的最佳方法是什么?

我发布的查询只是我自己的建议之一,但由于我在这里问这个问题,我显然不确定,并希望对查询有一些意见。

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

2 个答案:

答案 0 :(得分: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.

答案 1 :(得分: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子句来缩小结果集。