It's possible create a readonly database user at an Oracle Database?
How?
A user in an Oracle database only has the privileges you grant. So you can create a read-only user by simply not granting any other privileges.
When you create a user
CREATE USER ro_user
IDENTIFIED BY ro_user
DEFAULT TABLESPACE users
TEMPORARY TABLESPACE temp;
the user doesn't even have permission to log in to the database. You can grant that
GRANT CREATE SESSION to ro_user
and then you can go about granting whatever read privileges you want. For example, if you want RO_USER to be able to query SCHEMA_NAME.TABLE_NAME, you would do something like
GRANT SELECT ON schema_name.table_name TO ro_user
Generally, you're better off creating a role, however, and granting the object privileges to the role so that you can then grant the role to different users. Something like
Create the role
CREATE ROLE ro_role;
Grant the role SELECT access on every table in a particular schema
BEGIN
FOR x IN (SELECT * FROM dba_tables WHERE owner='SCHEMA_NAME')
LOOP
EXECUTE IMMEDIATE 'GRANT SELECT ON schema_name.' || x.table_name ||
' TO ro_role';
END LOOP;
END;
And then grant the role to the user
GRANT ro_role TO ro_user;
create user ro_role identified by ro_role;
grant create session, select any table, select any dictionary to ro_role;
Execute the following procedure for example as user system.
Set p_owner to the schema owner and p_readonly to the name of the readonly user.
create or replace
procedure createReadOnlyUser(p_owner in varchar2, p_readonly in varchar2)
AUTHID CURRENT_USER is
BEGIN
execute immediate 'create user '||p_readonly||' identified by '||p_readonly;
execute immediate 'grant create session to '||p_readonly;
execute immediate 'grant select any dictionary to '||p_readonly;
execute immediate 'grant create synonym to '||p_readonly;
FOR R IN (SELECT owner, object_name from all_objects where object_type in('TABLE', 'VIEW') and owner=p_owner) LOOP
execute immediate 'grant select on '||p_owner||'.'||R.object_name||' to '||p_readonly;
END LOOP;
FOR R IN (SELECT owner, object_name from all_objects where object_type in('FUNCTION', 'PROCEDURE') and owner=p_owner) LOOP
execute immediate 'grant execute on '||p_owner||'.'||R.object_name||' to '||p_readonly;
END LOOP;
FOR R IN (SELECT owner, object_name FROM all_objects WHERE object_type in('TABLE', 'VIEW') and owner=p_owner) LOOP
EXECUTE IMMEDIATE 'create synonym '||p_readonly||'.'||R.object_name||' for '||R.owner||'."'||R.object_name||'"';
END LOOP;
FOR R IN (SELECT owner, object_name from all_objects where object_type in('FUNCTION', 'PROCEDURE') and owner=p_owner) LOOP
execute immediate 'create synonym '||p_readonly||'.'||R.object_name||' for '||R.owner||'."'||R.object_name||'"';
END LOOP;
END;
you can create user and grant privilege
create user read_only identified by read_only;
grant create session,select any table to read_only;
It is not strictly possible in default db due to the many public executes that each user gains automatically through public.
Related
Example includes 2 roles -
READ_ONLY - for select access only
READ_WRITE - for update, insert, delete, drop, etc.
Now I want to fire pl/sql query to -
For loop to get all schema names:
Grant select on BGREADONLY to for User_X;
Please help with the exact piece of code..
you can try this procedure
CREATE or replace PROCEDURE grant_select(
in_var_username VARCHAR2,
in_var_grantee VARCHAR2)
AS
BEGIN
FOR rec IN (
SELECT owner, table_name FROM all_tables WHERE owner = in_var_username
)
LOOP
EXECUTE IMMEDIATE
'GRANT SELECT ON '||rec.owner||'.'||rec.table_name||' TO ' || in_var_grantee || ' with grant option ';
END LOOP;
END;
-- Call the procedure
exec grant_select('OWNER_SCHEMA','ROLE_TO_BE_GRANTED');
create or replace procedure rebuild_indexes(
p_table_name in varchar2 := 'SYSTEM'
) as
SQL_STR VARCHAR2(1000);
USERNAME VARCHAR2(50);
begin
Select USER into USERNAME from dual;
for indexes_to_rebuild in
(
select index_name
from dba_indexes
where owner = USERNAME
-- and table_name = p_table_name
) loop
SQL_STR := 'alter index '||USERNAME||'.'||indexes_to_rebuild.index_Name|| ' rebuild';
execute immediate SQL_STR;
end loop;
end;
EDIT:
The Error i get:
1- Error(16,51): PLS-00364: loop index variable 'INDEXES_TO_REBUILD'
use is invalid 2- Error(11,9): PL/SQL: SQL Statement ignored 3-
Error(12,14): PL/SQL: ORA-00942: table or view does not exist 4-
Error(16,9): PL/SQL: Statement ignored
It seems the user lacks a select right on dba_indexes. Have a DBA grant the user the right:
grant select on dba_indexes to thatusername;
Or better, as your are only interested in the user's indexes anyway, don't read dba_indexes at all, but user_indexes instead. Change
select index_name
from dby_indexes
where owner = USERNAME
to
select index_name
from user_indexes
There is nothing wrong with your code. The user which you have logged in does not have privileges to view DATA DICTIONARY objects.
So, Login first from a SYSDBA user and execute
GRANT SELECT on DBA_INDEXES to youruser;
Or, If you need the user to have privileges to view all the data dictionary ( all_objects etc.. )
GRANT SELECT ANY DICTIONARY TO youruser;
There is no need for Select USER into USERNAME from dual; just use USER directly. Try this one:
for indexes_to_rebuild in
(
SELECT INDEX_NAME
FROM USER_INDEXES
WHERE INDEX_TYPE IN ('NORMAL', 'BITMAP', 'FUNCTION-BASED BITMAP', 'FUNCTION-BASED NORMAL')
AND PARTITIONED = 'NO'
AND TEMPORARY = 'N'
-- and table_name = p_table_name
) loop
SQL_STR := 'alter index '||USER||'.'||indexes_to_rebuild.index_Name|| ' rebuild';
execute immediate SQL_STR;
end loop;
For partitioned indexes you have to execute REBUILD separately for each (sub-)partition.
I would like to grant a user i have created the permissions : select, insert, update, delete on a specific schema.
Do I need to be in the schema to do it ? (alter session set current_schema='my_schema';)
Thanks in advance
User often are asking for a single statement to Grant privileges in a single step.
there are multiple workarounds for not have a GRANT SELECT on all table
FOR x IN (SELECT * FROM user_tables)
LOOP
EXECUTE IMMEDIATE 'GRANT SELECT ON ' || x.table_name || ' TO <<someone>>';
END LOOP;
or
declare
cursor c1 is select table_name from user_tables;
cmd varchar2(200);
begin
for c in c1 loop
cmd := 'GRANT SELECT ON '||c.table_name|| <<TO YOURUSERNAME>>;
execute immediate cmd;
end loop;
end;
Oracle could implement a schema level grant
GRANT SELECT ON <schema name> to <<user>>
In Oracle I am trying to create PROCEDURE for delete any named object if it exists. I want to execute this query, select * from dba_objects where owner = 'TEST'. But when I create procedure I get errors:-
create or replace PROCEDURE DROPDATABASEOBJECT11(ObjName varchar2,ObjType varchar2,schemaName varchar2)
-----PROCEDURE FOR DROP ALL DATABASE OBJECTS-----
IS
v_counter number := 0;
begin
if ObjType = 'TABLE' then
select count(*) into v_counter select * from dba_objects where object_name = upper(ObjName);
if v_counter > 0 then
execute immediate 'drop table ' || ObjName || ' cascade constraints';
end if;
end if;
end;
I am getting error :-
Error(8,5): PL/SQL: SQL Statement ignored
Error(8,41): PL/SQL: ORA-00942: table or view does not exist
So how can I use that query in procedure?
I suspect the problem is access to DBA_OBJECTS. Regular users don't have privileges on DBA views. Even if they do have access to DBA views it's often through a role, and we cannot build PL/SQL programs (or views) against dependent objects granted through a role.
Solutions are:
Use ALL_OBJECTS instead
Have an authorised user (DBA) grant privileges on DBA_OBJECTS directly to your user.
The other potential problem is that you are not restricting the query and the dynamic SQL with the schema namespace. So, your code should look like this:
select count(*) into v_counter
from dba_objects
where object_type = ObjType
and owner = upper(SchemaName)
and object_name = upper(ObjName);
if v_counter > 0 then
execute immediate 'drop table ' || SchemaName || '.' || ObjName
|| ' cascade constraints';
end if;
How to grant permission for a user to all tables and sequences in Oracle?
Tables:
BEGIN
FOR R IN (SELECT owner, table_name FROM all_tables WHERE owner='<<REPLACE_WITH_YOUR_SCHEMA>>') LOOP
EXECUTE IMMEDIATE 'grant select on '||R.owner||'.'||R.table_name||' to <<REPLACE_WITH_USER>>';
END LOOP;
END;
Sequences:
BEGIN
FOR R IN (SELECT sequence_owner, sequence_name FROM all_sequences WHERE sequence_owner='<<REPLACE_WITH_YOUR_SCHEMA>>') LOOP
EXECUTE IMMEDIATE 'grant select on '||R.sequence_owner||'.'||R.sequence_name||' to <<REPLACE_WITH_USER>>';
END LOOP;
END;
This query can be used to set the appropriate system privileges.
GRANT SELECT ANY TABLE TO SOMEUSERNAME;
GRANT SELECT ANY SEQUENCE TO SOMEUSERNAME;
More information can be found here:
https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sqlrf/GRANT.html#GUID-20B4E2C0-A7F8-4BC8-A5E8-BE61BDC41AC3