I need to see all of a user's roles, including the roles inherited from a role.
Consider for example, this arrangement:
CREATE USER TEMPUSER1 IDENTIFIED BY "TEMPUSER1" ACCOUNT LOCK;
CREATE USER TEMPUSER2 IDENTIFIED BY "TEMPUSER2" ACCOUNT LOCK;
CREATE ROLE TEMP_ROLE1;
CREATE ROLE TEMP_ROLE2;
CREATE ROLE TEMP_ROLE3;
CREATE ROLE TEMP_ROLE4;
CREATE ROLE TEMP_ROLE5;
GRANT TEMP_ROLE1 TO TEMP_ROLE3;
GRANT TEMP_ROLE2 TO TEMP_ROLE3;
GRANT TEMP_ROLE3 TO TEMP_ROLE4;
GRANT TEMP_ROLE3 TO TEMP_ROLE5;
GRANT TEMP_ROLE4 TO TEMP_ROLE6;
GRANT TEMP_ROLE5 TO TEMP_ROLE6;
GRANT TEMP_ROLE2 TO TEMPUSER1;
GRANT TEMP_ROLE4 TO TEMPUSER1;
GRANT TEMP_ROLE6 TO TEMPUSER1;
GRANT TEMP_ROLE2 TO TEMPUSER2;
Then I want the result
GRANTED_USER | GRANTED_ROLE
---------------+---------------
TEMPUSER1 | TEMP_ROLE1
TEMPUSER1 | TEMP_ROLE2
TEMPUSER1 | TEMP_ROLE3
TEMPUSER1 | TEMP_ROLE4
TEMPUSER1 | TEMP_ROLE5
TEMPUSER2 | TEMP_ROLE1
TEMPUSER2 | TEMP_ROLE2
I'm using Oracle 11.2g, but I also want answers for future versions of Oracle. I'd like for this question to remain relevant if Oracle introduces new features that make this easier (like a view that just gives this to us straight up without writing our own queries).
Best Answer
Explanation
The view that tells us about
GRANT
ed roles isDBA_ROLE_PRIVS
. (There's alsoUSER_ROLE_PRIVS
, but it only shows roles granted to the current user.) However, this view does not give us all the inherited roles. Following through the user's roles recursively requires a "hierarchical" query, or more simply known as a recursive query.START WITH
clause should ensure thatGRANTEE = 'TEMPUSER1'
.GRANTEE
is one of the roles granted to the user of interest so far. This means ourCONNECT BY
clause should ensure thatPRIOR GRANTED_ROLE = GRANTEE
.CONNECT_BY_ROOT GRANTEE
, which will give us theGRANTEE
from the starting rows (and we started with our user of interest).TEMP_ROLE6
inheritsTEMP_ROLE3
. This means we'll need some kind ofDISTINCT
orGROUP BY
.The query
Assembling all that into a query gives us:
This gives the exact result desired.
Bonus info: Source of role
Here's an alternate query that includes some extra info about how the user got the role:
Notice that the query shows
'Direct GRANT'
when the role is granted to the user directly. This stands out a bit better than just showing the user name in the list.Notice that we still need the
DISTINCT
in the subquery. This is necessary becauseTEMPUSER1
getsTEMP_ROLE4
twice, once from a directGRANT
and once fromTEMP_ROLE6
. Without theDISTINCT
,TEMP_ROLE4
would show up twice as the source ofTEMP_ROLE3
.The result looks like this:
For all users
These queries can be easily adapter to show roles for all the users in the database. All that's needed is to change the
START WITH
clause to:For roles
The queries work equally well if you want to view the roles granted to a particular role. You need only specify the role name as the starting
GRANTEE
. For example,Or for all roles: