現(xiàn)在有一個用戶A,想把這個用戶A下面的所有的表查詢權(quán)限都賦予用戶X,該怎么做?同樣的問題,如果有4個用戶A、B、C、D,需要把這4個用戶下面所有的表的只讀權(quán)限賦予用戶X、Y、Z三個用戶,我們該怎么做?
在MySQL5.7中,可以創(chuàng)建用戶X,然后使用grant select on A.* to X這樣的方式分別把每一個庫下面所有的表都給用戶X授權(quán)就可以實現(xiàn)。在MySQL8.0版本中,有了角色role的概念,我們只要把ABCD四個庫下面所有表的只讀權(quán)限都賦予一個只讀角色,然后把這個只讀的角色再賦予XYZ三個用戶就可以了。
但是在Oracle中,沒有基于類似于MySQL中的schema級別的授權(quán),只能針對每一個用戶下面每一個表分別授權(quán)。下面有2種方式可以實現(xiàn)Oracle只讀用戶授權(quán)。
直接授予查詢權(quán)限
直接授權(quán)的方式就是把某一個用戶下面的所有的數(shù)據(jù)庫對象的對應(yīng)權(quán)限,一一授權(quán)給指定的另外一個用戶。下面我們演示一下具體的實現(xiàn)過程,把用戶mydb下面的所有表的只讀權(quán)限授權(quán)給my_ro_user用戶。
以下操作都是使用system用戶來執(zhí)行的。
- 創(chuàng)建一個只讀的用my_ro_user
create user my_ro_user identified by "my_ro_user";
- 給只讀的用戶授予連接權(quán)限
grant create session to my_ro_user;
- 把mydb下面的userinfo表的只讀權(quán)限授權(quán)給my_ro_user用戶
grant select on mydb.userinfo to my_ro_user;
上面只是把mydb下面的一個表授權(quán)給了my_ro_user用戶,如果我們需要把mydb用戶下面所有的表都授權(quán)給my_ro_user該如何做呢?在Oracle中沒有g(shù)rant select on mydb.* to my_ro_user這樣功能,只能指定每一個數(shù)據(jù)庫對象的名稱。可以參考如下的方式,可以循環(huán)地把mydb下面的每一張表的查詢權(quán)限都授權(quán)給my_ro_user用戶。
BEGIN
-- FOR t IN (SELECT * FROM user_tables)
FOR t in (SELECT owner, object_name, object_type FROM all_objects WHERE owner = UPPER('mydb') AND object_type IN ('TABLE','VIEW','PROCEDURE','FUNCTION','PACKAGE'))
LOOP
-- EXECUTE IMMEDIATE 'GRANT SELECT ON ' || t.table_name || ' TO my_ro_user';
IF t.object_type IN ('TABLE','VIEW') THEN
EXECUTE IMMEDIATE 'GRANT SELECT ON '||t.owner||'.'||t.object_name||' TO my_ro_user';
-- ELSIF t.object_type IN ('PROCEDURE','FUNCTION','PACKAGE') THEN
-- EXECUTE IMMEDIATE 'GRANT DEBUG ON mydb.'||t.object_name||' TO my_ro_user';
END IF;
END LOOP;
END;
完成上面的授權(quán)操作之后,我們使用新的用戶my_ro_user登錄Oracle數(shù)據(jù)庫之后,就可以查詢到mydb用戶下面的表中的數(shù)據(jù)了。
**注意:**此時在my_ro_user用戶下面執(zhí)行查詢語句的時候,需要指定mydb這個用戶名稱,在所有的表前面都需要增加上mydb.這個字符串才可以查詢到對應(yīng)的表,不能直接執(zhí)行select * from userinfo;,需要執(zhí)行select * from mydb.userinfo;才可以。如果想寫mydb.這個字符串就可以查詢到對應(yīng)的表,我們需要為my_ro_user賦予創(chuàng)建同義詞的權(quán)限,然后再my_ro_user下面創(chuàng)建同義詞才可以省略掉用戶名稱。
- 用system用戶給my_ro_user用戶授予創(chuàng)建同義詞的權(quán)限。
grant create synonym to my_ro_user;
- 用my_ro_user登錄Oracle然后執(zhí)行如下語句,將SQL語句的結(jié)果復(fù)制出來執(zhí)行即可批量創(chuàng)建出所有的同義詞。
select
'create or replace synonym my_ro_user.' || object_name|| ' for ' || owner || '.' || object_name|| ';' ,
'drop synonym my_ro_user.' || object_name|| ';'
from dba_objects
where owner in upper('mydb')
and object_type='TABLE';
執(zhí)行完上述SQL的結(jié)果集之后,my_ro_user在查詢mydb用戶下面的表時,就不用在指定mydb.字符串了。
通過角色來授予查詢權(quán)限
創(chuàng)建一個角色,然后把對某個數(shù)據(jù)庫下面的表的權(quán)限授予這個角色,然后再把這個角色賦予某一個用戶。這樣用戶就可以以某種角色去訪問某一個數(shù)據(jù)庫下面的表了。
具體實現(xiàn)方式參考如下:
- 創(chuàng)建只讀角色
create role my_readonly_role;
- 將數(shù)據(jù)庫下面所有的表授權(quán)給角色
/*mydb是Oracle的數(shù)據(jù)庫名稱,也是用戶名稱,userinfo是mydb下面的表,my_readonly_role是一個角色名稱*/
grant select on mydb.userinfo to my_readonly_role;
上面的方式比較麻煩,因為要對每一個表單獨對角色進(jìn)行授權(quán)。下面使用一個比較快的方式來解決這個授權(quán)的過程。
BEGIN
-- FOR t IN (SELECT * FROM user_tables)
FOR t in (SELECT owner, object_name, object_type FROM all_objects WHERE owner = UPPER('sunny_cmd') AND object_type IN ('TABLE','VIEW','PROCEDURE','FUNCTION','PACKAGE'))
LOOP
-- EXECUTE IMMEDIATE 'GRANT SELECT ON ' || t.table_name || ' TO my_readonly_role';
IF t.object_type IN ('TABLE','VIEW') THEN
EXECUTE IMMEDIATE 'GRANT SELECT ON '||t.owner||'.'||t.object_name||' TO my_readonly_role';
-- ELSIF t.object_type IN ('PROCEDURE','FUNCTION','PACKAGE') THEN
-- EXECUTE IMMEDIATE 'GRANT DEBUG ON mydb.'||t.object_name||' TO my_readonly_role';
END IF;
END LOOP;
END;
上面的SQL語句塊中,使用到了查詢某一個用戶下面所有的數(shù)據(jù)庫對象的查詢方式,如果要查詢某一個用戶下面所有的數(shù)據(jù)庫對象,可以通過如下的SQL語句:
/*查詢mydb用戶下面所有的數(shù)據(jù)庫對象,包括表、視圖、存儲過程、函數(shù)、包。*/
SELECT * FROM all_objects WHERE owner = UPPER('mydb') AND object_type IN ('TABLE','VIEW','PROCEDURE','FUNCTION','PACKAGE')
- 創(chuàng)建只讀用戶
create user my_ro_user identified by "my_ro_user";
- 給新創(chuàng)建的用戶授權(quán)登錄的權(quán)限
grant create session to my_ro_user;
- 把只讀角色授予新創(chuàng)建的只讀用戶
grant my_readonly_role to my_ro_user;
同義詞的使用
當(dāng)我們在只讀用戶下面,訪問其他用戶下面的只讀權(quán)限的表時,如果不想在SQL語句中指定其他用戶名稱,那么就需要在當(dāng)前只讀的用戶下面創(chuàng)建一個個表的同義詞,讓這個同義詞自動指向其他用戶下面對應(yīng)的表,這樣在只讀用戶下面就可以直接使用表名稱,不用在每一個表名稱前面增加用戶名稱了。
前提是當(dāng)前只讀的用戶,對另外一個用戶下的表,是有只讀的權(quán)限的,然后在當(dāng)前只讀用戶下創(chuàng)建同義詞才可用,否則只要同義詞沒有對應(yīng)的訪問權(quán)限,通過同義詞是不能訪問到對應(yīng)的數(shù)據(jù)表的。