.net Oracle-查询在哪些对象上授予哪些权限哪些角色

.net Oracle-查询在哪些对象上授予哪些权限哪些角色,.net,database,oracle,query-optimization,.net,Database,Oracle,Query Optimization,我需要查询一个Oracle数据库,并获取授予哪些权限的角色和对象。因为我将根据我正在创建的数据库管理系统中的配置撤销或授予对象上角色的权限 当我在要处理的对象上循环时,我需要知道角色是否已被授予该对象的任何特权。这需要在排队等待执行的授予或撤销之前完成 ODP.NET提供程序不支持运行多个Oracle语句, 它们必须一个接一个地运行,或者封装在BEGIN-END块中(然后作为单个语句计算)。有些语句甚至必须放在块内的executeimmediate语句中才能工作 我知道您可以在不中断任何操作的情

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

当我在要处理的对象上循环时,我需要知道角色是否已被授予该对象的任何特权。这需要在排队等待执行的
授予
撤销
之前完成

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

我知道您可以在不中断任何操作的情况下多次将对象上的相同权限授予角色,但是(如果我错了,请纠正我),从角色不具有的对象上的角色撤消权限将引发异常并中断整个块执行

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

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

我使用SQLTracker并发现Toad使用此查询查找授予角色对象的权限,并删除了roles 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数据库,我担心会出现性能问题

Q:查询Oracle数据库中哪些对象的哪些角色被授予哪些权限的最佳方式是什么?

我发布的查询只是我自己的一个建议,但是因为我在这里问这个问题,我显然不确定,我想了解一些关于查询的信息


我走对了吗?需要修改吗?我应该放弃它并使用完全不同的方法吗?

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

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.

我最终使用了问题中提供的查询,它似乎运行良好。 我需要的所有信息都在那里

但是我最终从
UNION ALL
中删除了
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子句来缩小结果集。

那么您是说只查询
ROLE\u TAB\u PRIVS
表就足够了?这是获得角色PRIVS的唯一方法。任何其他方式都会以任何方式隐式使用此表。这似乎是一个不错的答案,但我觉得我无法将其归类为正确的答案,这是一种防止在撤销特权时引发异常的解决方案。您的问题的答案是什么“查询Oracle数据库中哪些对象的哪些角色被授予哪些权限的最佳方式是什么?“-就像你写的那样,你可以从字典中进行自我查询。如果你把where子句放在查询中,这很容易,但是如果你想一次获取所有信息,然后通过列表从内存中本地查询,以防止乒乓球流量呢?”。假设您正试图管理世界另一端的数据库,如果您有1000个用户、40个角色和X*1000个对象,那么您必须进行大量乒乓查询才能获得所需的所有信息。更好的解决方案是一次获取所有信息,然后在imo本地查询。但我担心查询结果的大小,不知道是否有更好的一次?
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');