Skip to Main Content
  • Questions
  • How to automate the creation of the private synonyms based on the granted role

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Jermin.

Asked: May 11, 2009 - 8:48 pm UTC

Last updated: May 13, 2009 - 11:10 am UTC

Version: 9.2.0.1

Viewed 1000+ times

You Asked

Hi Tom,


To provide access on specific data only to a certain role, we think of creating views and using the private synonyms. As the private synonyms are for users not roles, We need to automate the creation of these private synonyms when a user is granted this role and drop them when the role is revoked.

Would you please guide how this can be done?

Appreciate your help

Regards,

Jermin


and Tom said...

you would have to maintain a list of what you wanted created and what you wanted to have dropped when you grant/revoke a role.

instead of granting the role, you would run a procedure, this procedure (which you will code) will not only grant the role, but would also issue the create synonym commands.

similar to:
ops$tkyte%ORA10GR2> create table t1 as select 'this is ops$tkyte.t1' data from dual;

Table created.

ops$tkyte%ORA10GR2> create table t2 as select 'this is ops$tkyte.t2' data from dual;

Table created.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> create role my_role;

Role created.

ops$tkyte%ORA10GR2> grant select on t1 to my_role;

Grant succeeded.

ops$tkyte%ORA10GR2> grant select on t2 to my_role;

Grant succeeded.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> create or replace procedure grant_role( p_role in varchar2, p_to in varchar2 )
  2  as
  3      l_str long;
  4      l_role dba_roles.role%type;
  5  begin
  6      select role into l_role from dba_roles where role = p_role;
  7      l_str := 'grant ' || l_role || ' to ' || dbms_assert.schema_name( p_to );
  8      execute immediate l_str;
  9      dbms_output.put_line( l_str );
 10
 11      for x in ( select owner, table_name
 12                   from dba_tab_privs
 13                  where grantee = l_role )
 14      loop
 15          l_str :=
 16          'create or replace synonym ' ||
 17                   p_to || '.' || x.table_name ||
 18          ' for "' || x.owner || '"."' || x.table_name || '"';
 19          execute immediate l_str;
 20          dbms_output.put_line( l_str );
 21      end loop;
 22  end;
 23  /

Procedure created.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> exec grant_role( 'MY_ROLE', 'SCOTT' );
grant MY_ROLE to SCOTT
create or replace synonym SCOTT.T2 for "OPS$TKYTE"."T2"
create or replace synonym SCOTT.T1 for "OPS$TKYTE"."T1"

PL/SQL procedure successfully completed.


be sure to see
http://asktom.oracle.com/tkyte/Misc/RolesAndProcedures.html
you'll need create ANY synonym granted directly to the owner of this procedure (which means of course, that you will need a code review and a half of the finished code - ANY privileges are powerful and should not be taken lightly)


And then the reverse when the role is revoked.


Of course - you have the problem of "what to do if we create a new table and grant select on it to a role" - you'll need to maintain this yourself as well (eg: you have lots of code to write)


I'm not sure I'd do this actually, there is NO NEED for the synonyms. None. There is NOTHING wrong with using schema.object in SQL - in fact, it is highly recommended.

Rating

  (3 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Jermin Dawoud, May 12, 2009 - 4:21 pm UTC

Thanks Tom.

Actually, there is a need for the synonyms to get the exact data based on the login user and executing the same form/report code. (ie no application change)

I was thinking of using triggers to achieve this (to fire when the role is granted or revoked). This way the private synonyms will be handled automatically.

What do you think? which table to set trigger on it?

Thanks again.
Tom Kyte
May 13, 2009 - 11:10 am UTC

... (ie no application change) ...

i hate those words. It is like writing a "hack", it'll be fragile and confusing and fraught with issues. Every time we try to "take a shortcut" it ends up being the long way around.


I hate triggers, I would not use a trigger. Think about what using a trigger would entail here. You would need to do DDL in the trigger. DDL commits. Therefore, it would have to be an autonomous transaction (non-transactional). Therefore, what happens when your trigger fires - does five things (that commit) and then something FAILS.


and you would not set a trigger on a table, it would be a system event trigger, but you SHOULD NOT DO IT, SHOULD NOT EVEN CONSIDER DOING IT

Jermin Dawoud, May 13, 2009 - 5:23 pm UTC

Thanks Tom.

We'll try to use Fine Grained Access Control instead of views & private synonyms.

schema.object

Eben Walker, October 14, 2009 - 5:09 pm UTC

you said "I'm not sure I'd do this actually, there is NO NEED for the synonyms. None. There is NOTHING wrong with using schema.object in SQL - in fact, it is highly recommended. "

I understand this concept but....years of coding later our implementation uses vast numbers of synonyms for each user. Is there no way to implement a 'path' which logically says "if you don't find it in this schema then go to schema "B"?

Further, when you fully define schema.object, what happens when you want/need to change the name of the base schema but retain the code? (If it is buried in volumes of forms and reports.)

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library