How to GRANT SELECT to ANY Table in a Schema to a Role (Oracle) - oracle

We wish to create an ANALYTICS role on our Oracle database. Anyone in this ANALYTICS role should be able to SELECT across any views in one (or more) schemas, but not ALL schemas.
We have a schema called ARIEL for example, and when we create new tables and views, we don't want to have to constantly apply GRANTS to the ANALYTICS role, and so we are hoping there is a way to apply a grant like this "GRANT SELECT ON ALL TABLES IN SCHEMA_X TO ANALYTICS"...note ANALYTICS is a role, not a schema.
Our DBA is saying this is not possible, and any future objects we create will need to have a grant applied, giving access to the ROLE.

"Our DBA is saying this is not possible, and any future objects we create will need to have a grant applied, giving access to the ROLE."
Your DBA is correct. You are searching for schema wide privileges(not implemented yet).
More: GRANT SELECT on all tables in a schema

Your DBA is correct that there would need to be a grant for every object that is created. It is possible to automate this which gives you basically the behavior that you want. I've done this in the past. But I'd seriously question the requirement before implementing it.
In general, new tables aren't created in production automatically, they're created as part of a build process. Part of that build process involves doing things like figuring out who should have access to the tables. Assuming that you're going through some sort of source control system, that means that you've got a history of the grants on objects and you can tie back changes in those grants to user stories. That's a useful thing to have.
If you have applications that are creating new tables in production dynamically (like an off the shelf app I was supporting) or doing something else where giving grants as part of a build process would be problematic, you can automate the process with a DDL trigger.
Create a DDL trigger that fires when a table is created
In that DDL trigger, use dbms_job to run a grant statement immediately after the CREATE TABLE statement commits
Something like this should work (untested)
CREATE OR REPLACE TRIGGER ddl_create
AFTER CREATE ON SCHEMA
DECLARE
l_job BINARY_INTEGER;
l_sql VARCHAR2(4000);
BEGIN
IF ora_dict_obj_type = 'TABLE'
THEN
l_sql := 'grant select on ' ||
ora_dict_obj_owner || '.' || ora_dict_obj_name ||
' to analytics';
DBMS_JOB.SUBMIT (
job => l_job,
what => l_sql );
END IF;
END;
Since the job runs asynchronously, it is possible that it will take a second or two to run after the table is created which may be an issue if the application immediately tries to run a query on the object. It is also possible that your DBA may disable jobs or limit the number of jobs that can run simultaneously which could further delay the grant. And if something goes wrong with the trigger or the job, this is a sufficiently obscure approach that it is going to take people a while to figure out where the problem is. DBAs aren't in the habit of looking for DDL triggers that may be granting privileges when someone decides, say, that they want a new role to automatically get insert access on the new table or when a grant didn't happen because jobs were disabled.

Related

grant select any table from one specific schema

I have just created a new read only user (TEMPDBREAD) for our developers # our oracle Database 11.2.0.4
Now they like read access to all tables from just one schema (TEMPDBUSER)
is there an alternative to grant select any table.
They should not be able to read the other schemes. But since the table structure often changes, it is difficult to justify everything manually.
That's why select any table is awarded very quickly and easier to place
Can i deny the access to the other schemes anyway?
Any Idea how i can solve this very simple?
BR Julian
Grant Table Access manually
Grant Select ANY Table
Nope. You either give them select any table and let them read any table in the database or you give them access to each table in TempDBUser individually. In the vast, vast majority of cases, you'd want to give them access to each table in TempDBUser (presumably via a role because there will be many developer accounts that need to run queries).
It isn't clear to me why giving object-level access is problematic for you. "Table structure changes" do not require new grants since they're just changes to existing objects. If you really mean that new tables are created frequently, you'd just want to incorporate the grants into your change control and deployment process.
If you have a packaged application that creates new tables periodically (a terrible practice), you could create a DDL trigger that issued the grant every time a new table was created in TempDBUser. You'd need a DDL trigger that submitted a job via the dbms_job package that did the actual grant which is a rather convoluted architecture but it works.
spool /tmp/grant_issue.sql
select 'grant select on TEMPDBUSER.' || table_name || ' TO TEMPDBREAD;' from dba_tables where owner='TEMPDBUSER' ;
spool off;
run the spool file.
sqlplus #/tmp/grant_issue.sql

I want to auto increment a column and make it as a primary key in oracle10g. But on trigger creation I get an error

I have created a Sequence for the table and on creation of a trigger I got the following error:
ORA-04089: cannot create triggers on objects owned by SYS.
Can someone explain me what is it and how can it be solved? Since I'm a beginner, is there a simple way to solve it?
MY TABLE NAME IS-testing.
create sequence example_seq
start with 1
increment by 1
nomaxvalue;
create trigger example_trigger
before insert on testing
for each row
begin
select example_seq.nextval into :new.id from dual;
end;
The error message is quite clear:
ORA-04089: cannot create triggers on objects owned by SYS.
So obviously you are logged in as SYS, and creating objects in that user;s schemas. You must not do this. SYS is the user who owns the data dictionary and all the objects which manage the database. Changing the SYS schema is, at best, bad practice and runs the risk of corrupting the database. Find out more.
What you need to do is create a new user, for your application objects. This is quite simple. Connect as SYSTEM (avoid using SYS for menial tasks):
create user your_name_here identified by << password >>
/
grant create session, create table, create sequence, create trigger
to your_name_here
/
Obviously you will need to grant more privileges. The full list is in the documentation.
Once you've created your new user you can connect to it and create all the objects you desire.

Grant Select on All VIEWS [current and future] in Schema X

I have a situation in our Oracle environment where I would like to be able to grant select permissions to a certain user/group on all views in a particular schema.
I realize that I could write a dynamic statement to iterate over all the views in the schema and grant permissions to them individually as shown here but I would like to be able to have this apply to all views that exist in the schema now or in the future.
I was also contemplating the possibility of writing a DDL trigger that could monitor for the creation of new views but setting permissions in a trigger isn't something I've seen done before and doesn't seem like accepted practice.
Basically, is there a VIEW analog to the GRANT EXECUTE ANY PROCEDURE?
The EXECUTE ANY PROCEDURE grant allows a user to execute any procedure in any schema in the database, not just those in a particular schema. You can grant a user the SELECT ANY TABLE privilege-- that will allow the user to query any table or view in any schema in the database not just those in a particular schema. That's the analogous privilege, it just seems unlikely that either is really what you're after.
Since views should not be created dynamically, this sort of requirement would normally be handled by simply including the appropriate GRANT statements in the scripts that create the new views which get promoted up through the environments. Dynamically granting privileges is generally frowned upon because it generally implies that you have issues with your change control process that need to be addressed.
I have, for third party applications that insist on creating new objects periodically, created a DDL trigger that grants privileges on new objects. In order to do that, you would need to submit a job that actually does the GRANT. A GRANT is a DDL statement so it issues an implicit commit and implicit commits aren't allowed in triggers, you have to have a separate job that runs moments after the object is created. This means that you end up with a number of moving pieces that generally makes your environment more complex.

Preventing a user from dropping its' own trigger

I have created a read only user A in Oracle DB. (who can access schema X but cannot alter anything) Then i am asked to give user A create table privilege on schema X.
However as far as i know, i can either give create any table privilege to user A or create table privilege. One of them is for creating table on his/her own schema, other one is for creating table on all schemas, which should not be preferred.
So i have given create any table privilege to user A and then created a trigger which prevents user A from creating a table on schemas other than X.
HOWEVER,
I needed to create the trigger as user A, and now user A can easily drop that trigger because A is the owner.
Is there any way i can prevent user A from dropping triggers even if he/she's the owner ?
As far as i experienced,user A does not need to have drop any trigger or administer database trigger privileges since trigger is already his/her own.
Is there any workaround for this ? Or should i search for an alternative way to give create table permission on other schemas.
Thank you in advance.
No, there is no way to prevent a user from dropping an object that it owns.
There's also no way to directly allow for user A to create objects in user X's schema, unless you start granting "ANY" privileges.
One possible workaround may be to create a stored procedure in user X's schema that will create objects in user X's schema (execute immediate) and grant EXECUTE privilege on said stored procedure to user A.
So, in this way, user A could do something like:
exec create_in_x_schema('create table blah(a number)');
And that procedure would just do an execute immediate on the string passed in.
A procedure that looks something like:
create or replace procedure create_in_x_schema(doit varchar2)
begin
execute immediate doit;
end;
/
ought to do it.
(Code is untested, but should give you some idea.)
Hope that helps.

ORACLE PL/SQL - SCHEDULE CREATE TABLE

I need to create a table every morning based on overnight generated data from a massive table. This will then be accessed by a handful of users form Excel.
My initial approach was to use a materilazed view and when this was rejected (for political reasons) to used Managed XLL but this was rejected for other reasons. I don't want to get messed up with Temporary tables and so really just need to know how to schedule an Oracle Create Table statement as our DBA says it can't be done.
My faith in SO users sasy otherwise though!
I don't see why you have to create a new table every morning and not use an existing one?
This creates your table from PL/SQL. Is this what you want?
CREATE OR REPLACE PROCEDURE make_table AS
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE your_table ( column_1 INT PRIMARY KEY, column_2 VARCHAR2(10) )';
END make_table;
/
EXEC make_table;
Your user needs to have the necessary grants, grants given by role don't apply to compiled PL/SQL code.

Resources