Problem
CREATE OR REPLACE VIEW statement fails with error ORA-01720: grant option does not exist
Solution
The statement will fail when there are invalid privileges granted on the view which would not have been granted normally, such as the owner of the view does not have the required privileges on the dependent objects in the other schemas
This is possible with the SYS user
Consider the following scenario:
Prepare the environment:
SQL> grant connect, create table, create view, unlimited tablespace to user_A identified by user_A;
SQL> grant connect, create table, create view, unlimited tablespace to user_B identified by user_B;
SQL> grant connect, create table, create view, unlimited tablespace to user_C identified by user_C;
User_A will create objects and will grant privileges to User_B:
SQL> conn user_a/user_A
SQL> create table t1 as select * from all_objects;
SQL> create view v1 as select * from t1;
SQL> grant select on v1 to user_B;
User_B now can exercise the grant privilege on view user_a.v1 and create a view based on that object, but will not be able to give access on the view:
SQL> conn user_B/user_B
SQL> select count(*) from user_A.v1;
COUNT(*)
----------
57239
SQL> create or replace view v1 as select * from user_A.v1;
View created.
SQL> select count(*) from v1;
COUNT(*)
----------
57239
SQL> grant select on v1 to user_C;
grant select on v1 to user_C
*
ERROR at line 1:
ORA-01720: grant option does not exist for 'USER_A.V1'
But the SYS user may still grant privileges on user_b.v1 view to other users, though those other users won't be able to exercise the privilege:
SQL> grant select on user_b.v1 to user_C;
Grant succeeded.
User_C still cannot access user_b.v1 as the grant is invalid:
SQL> conn user_C/user_C
Connected.
SQL> select count(*) from user_B.v1;
select count(*) from user_B.v1
*
ERROR at line 1:
ORA-01031: insufficient privileges
Now user_B cannot replace the view:
SQL> create or replace view v1 as select * from user_A.v1;
create or replace view v1 as select * from user_A.v1
*
ERROR at line 1:
ORA-01720: grant option does not exist for 'USER_A.V1'
Workarounds:
1) Drop the view and re-create from scratch. Dropping a view also drops all privileges granted on it
2) Identify the invalid privileges and either revoke them or do grant the missing privileges
To help identify the invalid privileges and formulate the required statements to fix them use the script below. Choose the correct option applicable for your environment, either GRANT or REVOKE, and optionally limit the query to specific schemas and objects:
with
options(opt) as (
select /* uncomment required option */
'GRANT'
-- 'REVOKE'
from dual
),
owners(owner) as ( -- filter by schemas
select '%' from dual
),
objects(object_name) as ( -- filter by objects
select '%' from dual
),
dependencies as (
select
connect_by_root owner owner,
connect_by_root name name,
type,
referenced_owner,
referenced_name,
referenced_type
from dba_dependencies t
where referenced_owner <> owner and owner = connect_by_root owner
connect by
prior referenced_owner = owner
and prior referenced_name = name
and referenced_type in ( 'TABLE', 'VIEW')
start with
type='VIEW'
and owner like (select owner from owners)
and name like (select object_name from objects)
)
select distinct
case (select opt from options)
when 'GRANT' then
'grant ' || p1.privilege
|| ' on ' || d.referenced_owner ||'.'|| d.referenced_name
|| ' to ' || p1.owner || ' with grant option;'
when 'REVOKE' then
'revoke ' || p1.privilege
|| ' on ' || p1.owner||'.'||table_name
|| ' from ' || p1.grantee ||';' end command
from
dba_tab_privs p1
join dependencies d
on d.owner = p1.owner and d.name = p1.table_name and p1.type = d.type
where
p1.type='VIEW' and p1.owner like (select owner from owners)
and p1.table_name like (select object_name from objects)
and d.referenced_type in ( 'TABLE', 'VIEW')
and not exists (
select * from dba_tab_privs p2
where p2.grantee=p1.owner
and p2.privilege = p1.privilege
and p2.owner = d.referenced_owner
and p2.table_name = d.referenced_name
and p2.grantable='YES')
No comments:
Post a Comment