This question already has answers here:
Grant Select on all Tables Owned By Specific User
(5 answers)
Closed 5 years ago.
The situation is I have two schemas: A and B. I have a restricted user that I need to give a privilege do SELECT queries in B schema and just it. How can I grant this user?
You can't.
The best you can do is grant user a 'select' privilege each table in schema b.
this query will generate the commands you'll need:
select 'grant select on A.'||table_name||' to B;'
from dba_Tables
where owner = 'A';
The problem with this, is in the case you will want to add new table to A. then you'll have to grant the privilege on it separately. it will not do it automatically..
You may find you do not have access to dba_tables,
The following block of code run in the owning schema (a) will grant permissions to all tables, to the user b
BEGIN
FOR t IN (SELECT * FROM user_tables)
LOOP
EXECUTE IMMEDIATE 'GRANT SELECT ON ' || t.table_name || ' TO b';
END LOOP;
END;
Related
This question already has answers here:
Can GRANT be used inside an Oracle Store Procedure?
(2 answers)
Closed 5 years ago.
I have to provide multiple permissions to different users. Currently i run script manually(one by one) in oracle like -
GRANT SELECT ON xyz.a_BCKUP TO abc;
GRANT SELECT ON xyz.b_BCKUP TO abc;
GRANT SELECT ON xyz.c_BCKUP TO abc;
GRANT SELECT,INSERT,DELETE,UPDATE ON abc.map1 TO xyz;
GRANT SELECT,INSERT,DELETE,UPDATE ON abc.map2 TO xyz;
GRANT SELECT,INSERT,DELETE,UPDATE ON abc.map3 TO xyz;
My objective is to run it at one go. Can i just put in a SP and execute. Will it work in ORACLE ? I am not very sure about this. Any ideas to do it without SPs!!
CREATE or replace
PROCEDURE GRANTS AS
BEGIN
*grant permission script*
END;
You can use Dynamic SQL for this
CREATE OR REPLACE PROCEDURE GRANT_PROC AS
v_sql VARCHAR2(10000);
BEGIN
v_sql := 'GRANT SELECT ON xyz.a_BCKUP TO abc';
EXECUTE IMMEDIATE v_sql;
END;
I have written a procedure to grant permissions on all the tables of a particular schema to rest other schemas.
create or replace PROCEDURE GRANTS_PROC
IS
CURSOR GRANTS_CURSOR
IS
SELECT 'GRANT SELECT, INSERT, UPDATE, DELETE ON "'
||T.OWNER
||'"."'
||TABLE_NAME
||'" TO '
||(SELECT rtrim(listagg(U.username||',')
within group (order by U.username),',') USERNAME
FROM ALL_USERS U
WHERE U.USERNAME!=T.OWNER
AND U.USERNAME IN
('AAA','BBB','CCC','DDD','EEE','FFF','GGG','HHH','III'))||';' FINAL_TXT
FROM ALL_TABLES T
WHERE T.OWNER IN
('AAA','BBB','CCC','DDD','EEE','FFF','GGG','HHH','III')
ORDER BY T.OWNER,UPPER(T.TABLE_NAME);
BEGIN
--DBMS_OUTPUT.PUT_LINE('CURSOR_GRANTS.FINAL_TXT');
--QRY_TEXT:='ABC';
FOR CURSOR_GRANTS IN GRANTS_CURSOR
LOOP
DBMS_OUTPUT.PUT_LINE(CURSOR_GRANTS.FINAL_TXT);
EXECUTE IMMEDIATE CURSOR_GRANTS.FINAL_TXT;
END LOOP;
END;
/
The above procedure compiled successfully, but while execution it is not getting into FOR loop to run the EXECUTE IMMEDIATE block but PL/SQL procedure compiled successfully.
What could be done to fix my procedure and make it work?
All_USERS and ALL_TABLES should be changed to DBA_USERS and DBA_TABLES, Hence my procedure works.
Because the all_tables view shows the tables that the owner of the stored procedure has privileges on, so, unless the stored procedure is being created by a privileged user, or a user that already has those grants (with grant option so they can actually give the privileges), there may be nothing in all_tables that qualifies.
Without using GRANT SELECT ANY TABLE, how would I grant access to all tables from only one schema.
Example:
There are three users. u1, u2, u3.
u1 need access to all the tables that u2 has but doesn't need access to tables that u3 has.
I could loop through all the tables and grant them individually.
But what about new tables that u2 creates later. u1 needs those tables too.
How could I automatically grant those new tables as well?
I believe you can do this with an AFTER CREATE trigger. The following example doesn't handle all your U1/U2/U3 logic - you'll have to add that - but it should give you the basic idea:
CREATE TRIGGER AUTO_GRANT
AFTER CREATE ON SCHEMA
BEGIN
IF ORA_DICT_OBJ_TYPE = 'TABLE' THEN
EXECUTE IMMEDIATE 'GRANT SELECT ON ' || ora_dict_obj_owner || '.' ||
ora_dict_obj_name ' TO U1';
END IF;
END AUTO_GRANT;
Docs here.
Best of luck.
I am puzzled. I have a user which can run the below in SQL Developer and it works perfectly.
begin
FOR C IN (SELECT TABLE_NAME FROM ALL_TABLES
WHERE TABLE_NAME LIKE 'TEMP_%'
AND OWNER = '<user name in caps>')
LOOP
EXECUTE IMMEDIATE('DROP TABLE <user name in caps>.' || C.table_name || ' PURGE');
END LOOP;
end;
However - if I wrap the functionality in a stored procedure and run it, while no exceptions are thrown, the table beginning with "temp" does not delete. I actually am deleting from three different schemas - thus the repetition.
CREATE OR REPLACE PROCEDURE DELETETEMPTABLES AS
BEGIN
--DROP ANY TABLES THAT START WITH "TEMP_"
FOR C IN (SELECT TABLE_NAME FROM ALL_TABLES
WHERE TABLE_NAME LIKE 'TEMP_%'
AND OWNER = '<user name in caps>')
LOOP
EXECUTE IMMEDIATE('DROP TABLE <user name in caps>.' || C.table_name || ' PURGE');
END LOOP;
FOR C IN (SELECT TABLE_NAME FROM ALL_TABLES
WHERE TABLE_NAME LIKE 'TEMP_%'
AND OWNER = '<user name in caps>')
LOOP
EXECUTE IMMEDIATE('DROP TABLE <user name in caps>.' || C.table_name || ' PURGE');
END LOOP;
FOR C IN (SELECT TABLE_NAME FROM ALL_TABLES
WHERE TABLE_NAME LIKE 'TEMP_%'
AND OWNER = '<user name in caps>')
LOOP
EXECUTE IMMEDIATE('DROP TABLE <user name in caps>.' || C.table_name || ' PURGE');
END LOOP;
exception
WHEN OTHERS THEN
log_errors (p_error_message => 'Nightly Processing->DeleteTempTables-> ' ||SQLERRM);
END DELETETEMPTABLES;
Justin is correct. But you can often use AUTHID to overcome the priv issue. Try:
CREATE OR REPLACE PROCEDURE DELETETEMPTABLES
AUTHID CURRENT_USER
AS
This is called "invokers rights" in Oracle. The default is definers rights (authid definer). For more see here and here.
The use of roles in a subprogram depends on whether it executes with
definer's rights or invoker's rights. Within a definer's rights
subprogram, all roles are disabled. Roles are not used for privilege
checking, and you cannot set roles.
Within an invoker's rights subprogram, roles are enabled (unless the
subprogram was called directly or indirectly by a definer's rights
subprogram). Roles are used for privilege checking, and you can use
native dynamic SQL to set roles for the session. However, you cannot
use roles to grant privileges on template objects because roles apply
at run time, not at compile time.
Most likely, this is a privilege issue.
ALL_TABLES lists all the tables that you have privileges on. When you run it interactively, that includes all the tables that you have privileges on via a role. When you try to create a stored procedure, however, privileges that are granted via a role are excluded and you only see those tables that you have direct grants on. If you want your code to work, the owner of the objects (or the DBA) would need to grant privileges on the object directly to the procedure owner, not via a role. Realistically, the owner of the procedure would also need the DROP ANY TABLE privilege granted directly to it (not via a role like DBA) for the DROP TABLE statements to succeed.
I have two users Bob and Alice in Oracle, both created by running the following commands as sysdba from sqlplus:
create user $blah identified by $password;
grant resource, connect, create view to $blah;
I want Bob to have complete access to Alice's schema (that is, all tables), but I'm not sure what grant to run, and whether to run it as sysdba or as Alice.
Happy to hear about any good pointers to reference material as well -- don't seem to be able to get a good answer to this from either the Internet or "Oracle Database 10g The Complete Reference", which is sitting on my desk.
AFAIK you need to do the grants object one at a time.
Typically you'd use a script to do this, something along the lines of:
SELECT 'GRANT ALL ON '||table_name||' TO BOB;'
FROM ALL_TABLES
WHERE OWNER = 'ALICE';
And similar for other db objects.
You could put a package in each schema that you need to issue the grant from which will go through all call each GRANT statement via an EXECUTE IMMEDIATE.
e.g.
PROCEDURE GRANT_TABLES
IS
BEGIN
FOR tab IN (SELECT table_name
FROM all_tables
WHERE owner = this_user) LOOP
EXECUTE IMMEDIATE 'GRANT SELECT, INSERT, UPDATE, DELETE ON '||tab.table_name||' TO other_user';
END LOOP;
END;
There are many things to consider. When you say access, do you want to prefix the tables with the other users name? You can use public synonyms so that you can hide the original owner, if that is an issue. And then grant privs on the synonym.
You also want to plan ahead as best you can. Later, will you want Frank to be able to access Alice's schema as well? You don't want to have to regrant privileges on N number of tables. Using a database role would be a better solution. Grant the select to role "ALICE_TABLES" for example and when another user needs access, just grant them privilege to the role. This helps to organize the grants you make inside the DB.
Another solution if you have different owner:
BEGIN
FOR x IN (SELECT owner||'.'||table_name ownertab
FROM all_tables
WHERE owner IN ('A', 'B', 'C', 'D'))
LOOP
EXECUTE IMMEDIATE 'GRANT SELECT ON '||x.ownertab||' TO other_user';
END LOOP;
END;