Oracle Read only access to specific user - oracle

I have a schema and many users in it. For development I would like to give permission to the user to only read the tables and not having permission to manipulate database. Are there any commands to set access rights for a particular user to read only?

As Ed commented, you aren't allowed to do anything unless granted. For read-only users, you'd grant only the SELECT privilege on your tables. If you have only a few of them, do it manually. Otherwise, create a procedure which will do it for you. Here's an example.
These are my tables:
SQL> select * from tab;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
BONUS TABLE
DEPT TABLE
EMP TABLE
LINKS TABLE
SALGRADE TABLE
A procedure which loops through all tables in my schema and grants SELECT to user passed as a parameter:
SQL> create or replace procedure p_grant_ro(par_user in varchar2) is
2 l_str varchar2(200);
3 begin
4 for cur_r in (select table_name from user_tables
5 order by table_name
6 )
7 loop
8 l_str := 'grant select on ' || cur_r.table_name ||
9 ' to ' || dbms_assert.schema_name(par_user);
10 dbms_output.put_line(l_str);
11 execute immediate(l_str);
12 end loop;
13 end;
14 /
Procedure created.
Testing:
SQL> set serveroutput on;
SQL> exec p_grant_ro('MIKE');
grant select on BONUS to MIKE
grant select on DEPT to MIKE
grant select on EMP to MIKE
grant select on LINKS to MIKE
grant select on SALGRADE to MIKE
PL/SQL procedure successfully completed.
SQL>
If you wonder what's the purpose of dbms_assert function's call: preventing possible SQL injection. Function takes care that parameter is an existing schema name.
SQL> exec p_grant_ro('TECH_DELHI');
BEGIN p_grant_ro('TECH_DELHI'); END;
*
ERROR at line 1:
ORA-44001: invalid schema
ORA-06512: at "SYS.DBMS_ASSERT", line 266
ORA-06512: at "SCOTT.P_GRANT_RO", line 8
ORA-06512: at line 1
SQL>

You should be able to configure this in e.g. MYSQL Workbench.
I think there is also a way to link this to an Apex user.

Related

Restrict creation of table on sunday in oracle

Question: create a pl/sql using a trigger to restrict creation of any
table on Sunday
I tried
CREATE OR REPLACE TRIGGER sunday_trigger
BEFORE CREATE ON ALSPRD
FOR EACH ROW
DECLARE
v_day DATE := TRUNC(SYSDATE);
BEGIN
IF TO_CHAR(v_day,'DY')IN ('SUN') THEN
REVOKE create table from harsh;
END IF;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Error is:'||SQLERRM);
END;
It creating error ORA-30506: system triggers cannot be based on tables or views
I'd suggest a different approach.
Connected as SYS, create a trigger that prevents user (scott in my example) to create anything on desired day (I'll use Monday so that I could test whether it works as planned).
SQL> show user
USER is "SYS"
SQL>
SQL> create or replace trigger sunday_trigger
2 before create on scott.schema
3 begin
4 if to_char(sysdate, 'DY', 'nls_date_language = english') = 'MON'
5 then
6 raise_application_error(-20000, 'You can not create any objects on Monday');
7 end if;
8 end;
9 /
Trigger created.
Let's test it:
SQL> connect scott/tiger
Connected.
SQL> select to_char(sysdate, 'DY', 'nls_date_language = english') today from dual;
TODAY
------------
MON
SQL> create table so_test (id number);
create table so_test (id number)
*
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-20000: You can not create any objects on Monday
ORA-06512: at line 4
SQL> create or replace procedure p_test is
2 begin
3 null;
4 end;
5 /
create or replace procedure p_test is
*
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-20000: You can not create any objects on Monday
ORA-06512: at line 4
SQL>
Let's pretend it is tomorrow (Tuesday):
SQL> connect sys as sysdba
Enter password:
Connected.
SQL> select sysdate from dual;
SYSDATE
--------
21.06.21
SQL> alter system set fixed_date = '22.06.21';
System altered.
SQL> connect scott/tiger
Connected.
SQL> select to_char(sysdate, 'DY', 'nls_date_language = english') today from dual;
TODAY
------------
TUE
SQL> create table so_test (id number);
Table created.
SQL> create or replace procedure p_test is
2 begin
3 null;
4 end;
5 /
Procedure created.
SQL>
Looks OK to me.
Revoke user rights to create tables from harsh.
Create another user <OWNER_PROC> with rights to create tables.
Make a procedure <CREATE_TABLE_PROC> that creates tables and in this procedure you can make any logic.
Grant execute on <OWNER_PROC>.<CREATE_TABLE_PROC> to harsh.

DELETE ANY TABLE TO TEST_USER_ROLE (except one table?)

Is there any possibility to revoke "delete" from one table over "any table" privilege?
My user_role has GRANT DELETE ANY TABLE TO TEST_USER_ROLE privilege.
I would like leave it except one table.
I tried with REVOKE DELETE on TEST_TABLE from TEST_USER_ROLE but I got "cannot REVOKE privileges you did not grant" error which is correct. Any advice?
Thanks!
Revoke DELETE ANY TABLE and grant DELETE, separately. A lot of grants? Certainly, but you don't have to do it manually - write query that'll create those statements for you. Or, do it in a PL/SQL procedure, in a loop (omit table you don't want to include).
Say if you need help in composing such a code.
Here's a PL/SQL procedure which does the job:
SQL> set serveroutput on
SQL>
SQL> declare
2 l_grantee varchar2(30) := 'MIKE';
3 l_str varchar2(200);
4 begin
5 for cur_r in (select table_name
6 from user_tables
7 where table_name <> 'DEPT'
8 and rownum <= 5
9 )
10 loop
11 l_str := 'grant delete on ' || cur_r.table_name || ' to ' || l_grantee;
12 dbms_output.put_line(l_str);
13 execute immediate l_str;
14 end loop;
15 end;
16 /
grant delete on DPT to MIKE
grant delete on TABLE_B to MIKE
grant delete on TABLE_A to MIKE
grant delete on EMPLOYEES to MIKE
grant delete on TABLE_NAME to MIKE
PL/SQL procedure successfully completed.
SQL>
. What does it do?
line #2, l_grantee: user I'm going to grant the privilege to
cursor FOR loop: just for example, I'll omit table dept and (to make a list shorter) grant delete for only 5 tables
line #11: compose the grant statement
line #12: display it (so that you'd have evidence of what you did)
line #13: grant!
If there are more owners included, you'd use ALL_TABLES or even DBA_TABLES instead of USER_TABLES (line #6) and include the OWNER column (because many users can have a table with the same name).

How to run a query on different schemes at once

I want to run a query on different schemes to get data and export it. I use the following code
DECLARE
sql_statment VARCHAR2(2000);
BEGIN
FOR c IN (SELECT brchcode FROM brchs) LOOP
sql_statment := 'select distinct ''' || c.brchcode ||''', t.risuid from ' || c.brchcode ||
'.reg_individualacnt_detail t
where t.historytypecode = 60';
EXECUTE IMMEDIATE sql_statment;
END LOOP;
END;
where brchcode is the name of different schemes
I can't see any output. what can I do?
Code you wrote can't work as you have to return the result into something; it is PL/SQL and requires an INTO clause. As you chose to return two values (columns) and multiple rows, that can't be a scalar variable; you could pick ref cursor or a collection, for example.
Here's an example which shows one option.
I'll be using two schemas: SCOTT (current schema) and HR. Both will be having the DEPT table.
As Scott already has it, I'll create one in HR schema and grant access to Scott (otherwise, Scott won't even see it and the procedure (i.e. the function) will fail):
SQL> connect hr/hr
Connected.
SQL> create table dept (deptno number, dname varchar2(10), loc varchar2(10));
Table created.
SQL> insert into dept values (55, 'IT', 'Zagreb');
1 row created.
SQL> grant select on dept to scott;
Grant succeeded.
SQL> commit;
Commit complete.
Back to Scott, to create a table (which contains schema names I'll be selecting from) and a function. I chose to return REF CURSOR; you could return something else, if you want.
SQL> connect scott/tiger
Connected.
SQL> create table brchs (brchcode varchar2(10));
Table created.
SQL> insert into brchs (brchcode)
2 select 'scott' from dual union all
3 select 'hr' from dual;
2 rows created.
SQL> create or replace function f_br
2 return sys_refcursor
3 is
4 l_str varchar2(4000);
5 l_rc sys_refcursor;
6 begin
7 for cur_r in (select brchcode from brchs) loop
8 l_str := l_str ||
9 'union all
10 select ' || chr(39)|| cur_r.brchcode ||chr(39) || ', d.dname
11 from ' || cur_r.brchcode ||'.dept d
12 where d.deptno > 0';
13 end loop;
14
15 l_str := ltrim(l_str, 'union all');
16
17 open l_rc for l_str;
18 return l_rc;
19 end;
20 /
Function created.
SQL>
Finally, testing:
SQL> select f_br from dual;
F_BR
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
'SCOT DNAME
----- --------------
scott ACCOUNTING
scott RESEARCH
scott SALES
scott OPERATIONS
hr IT
SQL>

How to grant trigger access to a table

I'm getting an error message for a trigger I've successfully created.
I've tried...
GRANT SELECT ON OTHER_TABLE TO [me];
call SYS.DBA_ASSIST.GRANT_OBJ_PERMS('dbo.MYTABLE','SELECT','dbo.OTHER_TABLE');`
Here is the code for the trigger...
CREATE OR REPLACE TRIGGER PREVENT_INVALID_ID
BEFORE INSERT OR UPDATE ON dbo.MYTABLE
FOR EACH ROW
DECLARE ROW_COUNT NUMBER;
BEGIN
SELECT COUNT(*) INTO ROW_COUNT
FROM [OTHER_TABLE] WHERE OTHER_TABLE_ID = :new.MYTABLE_ID;
IF ROW_COUNT = 0 THEN
RAISE_APPLICATION_ERROR(-20101, 'The ID provided is invalid.');
END IF;
END;`
The error message in user_errors says, "PL/SQL: ORA-00942: table or view does not exist"
Any idea how I can get the trigger to access OTHER_TABLE?
I understand that it is not possible to grant access/authorizations to triggers. But I'm unclear what code I need to run in order to allow the trigger to work.
Thanks in advance,
josh
If both MYTABLE and OTHER_TABLE belong to the same user, no privilege is required:
SQL> show user
USER is "SCOTT"
SQL> create table other_table (other_Table_id number);
Table created.
SQL> create table mytable (mytable_id number);
Table created.
SQL> create or replace trigger prevent_invalid_id
2 before insert or update on mytable
3 for each row
4 declare
5 row_count number;
6 begin
7 select count(*) into row_count
8 from other_table where other_table_id = :new.mytable_id;
9
10 if row_count = 0 then
11 raise_application_error(-20101, 'The ID provided is invalid');
12 end if;
13 end;
14 /
Trigger created.
SQL>
However, if they belong to different user, then OTHER_TABLE's owner has to grant SELECT privilege to me. Though, that's not enough - you have to either precede OTHER_TABLE with its owner name (e.g. other_user.other_table), or create a synonym in my own schema which points to other user's OTHER_TABLE. For example:
SQL> drop table other_table;
Table dropped.
SQL> connect mike/lion#xe
Connected.
SQL> create table other_table (other_Table_id number);
Table created.
SQL> grant select on other_table to scott;
Grant succeeded.
SQL> connect scott/tiger#xe
Connected.
SQL> create or replace trigger prevent_invalid_id
2 before insert or update on mytable
3 for each row
4 declare
5 row_count number;
6 begin
7 select count(*) into row_count
8 from MIKE.other_table where other_table_id = :new.mytable_id;
9
10 if row_count = 0 then
11 raise_application_error(-20101, 'The ID provided is invalid');
12 end if;
13 end;
14 /
Trigger created.
SQL>
Note line 8: MIKE.other_table.
Just to show what happens if you omit/remove owner's name:
SQL> l8
8* from MIKE.other_table where other_table_id = :new.mytable_id;
SQL> c/mike.//
8* from other_table where other_table_id = :new.mytable_id;
SQL> l
1 create or replace trigger prevent_invalid_id
2 before insert or update on mytable
3 for each row
4 declare
5 row_count number;
6 begin
7 select count(*) into row_count
8 from other_table where other_table_id = :new.mytable_id;
9
10 if row_count = 0 then
11 raise_application_error(-20101, 'The ID provided is invalid');
12 end if;
13* end;
SQL> /
Warning: Trigger created with compilation errors.
SQL> show err
Errors for TRIGGER PREVENT_INVALID_ID:
LINE/COL ERROR
-------- -----------------------------------------------------------------
4/3 PL/SQL: SQL Statement ignored
5/8 PL/SQL: ORA-00942: table or view does not exist
SQL>
See? ORA-00942.
Figured it out: GRANT SELECT ON OTHER_TABLE TO dbo
What threw me off is the use the words 'table owner' when I was looking for instructions on how to do this. I thought I was the table owner. Rather, it's the schema (dbo) that needs the privileges.

access to function - ORA-00904: invalid identifier

I am new to oracle, please assist.
I have written a function similar to here in schemaB, with minor alterations.
When I run the query from above function, in schemaA, it runs fine and returns the sequence.
select schemaB.sequence_name_seq.nextVal from dual;
Running the function from schemaB ofcourse return the sequence as expected.
However, when I try to access the same function (containing the above query) from schemaA, it gives me an error:
"ORA-00904: invalid identifier"
I have granted EXECUTE privileges to userA of schemaA (confirmed from 'DBA_TAB_PRIVS' table).
Function:
create or replace Function nextSeq
(
tableName in VARCHAR2
)return NUMBER as
nextNum Number;
begin
EXECUTE IMMEDIATE 'select '||tableName||'_SEQ.nextval from dual' into nextNum;
return nextNum;
END nextSeq;
To Call:
select nextSeq('SCHEMAB.TABLENAME') from dual;
Here's how I'd do that: connected as SCOTT, I'm creating a sequence and a function; then I'll grant EXECUTE on the function to user MIKE:
SQL> show user
USER is "SCOTT"
SQL> create sequence dept_seq;
Sequence created.
SQL> create or replace function nextseq (tablename in varchar2)
2 return number
3 as
4 nextnum number;
5 begin
6 execute immediate 'select ' || tablename||'_seq.nextval from dual' into nextnum;
7 return nextnum;
8 end;
9 /
Function created.
SQL> select nextseq('dept') from dual;
NEXTSEQ('DEPT')
---------------
1
SQL> grant execute on nextseq to mike;
Grant succeeded.
SQL>
Connect as MIKE and use SCOTT's function:
SQL> connect mike/lion#xe
Connected.
SQL> show user
USER is "MIKE"
SQL> select scott.nextseq('dept') from dual;
SCOTT.NEXTSEQ('DEPT')
---------------------
2
SQL>
As you can see it works. When compared to your code, the difference is here:
You: select nextSeq('SCHEMAB.TABLENAME') from dual;
Me : select scott.nextseq('dept') from dual;
You shouldn't precede table name with the owner, but the function name.

Resources