如何将对所有数据库对象的只读访问权限授予 oracle 中的另一个用户?
How to grant read-only access to all the DB objects to another user in oracle?
我尝试将对所有数据库对象的只读访问权限授予另一个可能不存在的用户。这就是我尝试这样做的方式:
DECLARE
user_exists NUMBER;
BEGIN
SELECT COUNT(*) INTO user_exists FROM ALL_USERS WHERE USERNAME = '${user}';
IF user_exists > 0 THEN
FOR obj IN (SELECT object_name, object_type
FROM all_objects
WHERE owner = '${owner}'
AND object_type IN ('TABLE', 'VIEW', 'PROCEDURE', 'FUNCTION', 'PACKAGE'))
LOOP
IF obj.object_type IN ('TABLE', 'VIEW') THEN
EXECUTE IMMEDIATE 'GRANT SELECT ON ${owner}.' || obj.object_name ||
' TO ${user}';
ELSIF obj.object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE') THEN
EXECUTE IMMEDIATE 'GRANT EXECUTE ON ${owner}.' || obj.object_name || ' TO ${user}';
END IF;
END LOOP;
END IF;
END;
脚本失败并显示以下消息:
Message : ORA-00942: table or view does not exist
ORA-06512: at line 16
ORA-06512: at line 16
我做错了什么?
除非我错了,所有 在你的代码中看起来像 ${something}
的东西都是错误的。
它应该做什么?您真的查询过 ALL_OBJECTS
并查看其中的内容吗?看起来好像你认为它们会自动被某种存在的东西所取代......呵呵,只是在你的想象中?
如果它是一个程序,那么您可以将所有者(授权人)和另一个用户(被授权人)作为参数传递。您编写的代码可以重复使用,其中大部分:
SQL> CREATE OR REPLACE PROCEDURE p_grant (par_owner IN VARCHAR2,
2 par_grantee IN VARCHAR2)
3 AS
4 user_exists NUMBER;
5 l_str VARCHAR2 (1000);
6 BEGIN
7 SELECT COUNT (*)
8 INTO user_exists
9 FROM all_users
10 WHERE username = DBMS_ASSERT.schema_name (par_grantee);
11
12 IF user_exists > 0
13 THEN
14 FOR obj IN (SELECT object_name, object_type
15 FROM all_objects
16 WHERE owner = DBMS_ASSERT.schema_name (par_owner)
17 AND object_type IN ('TABLE',
18 'VIEW',
19 'PROCEDURE',
20 'FUNCTION',
21 'PACKAGE')
22 AND STATUS = 'VALID')
23 LOOP
24 IF obj.object_type IN ('TABLE', 'VIEW')
25 THEN
26 l_str :=
27 'GRANT SELECT ON '
28 || par_owner
29 || '.'
30 || obj.object_name
31 || ' TO '
32 || par_grantee;
33 ELSIF obj.object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE')
34 THEN
35 l_str :=
36 ' grant execute on '
37 || par_owner
38 || '.'
39 || obj.object_name
40 || ' to '
41 || par_grantee;
42 END IF;
43
44 DBMS_OUTPUT.put_line (l_str);
45
46 EXECUTE IMMEDIATE l_str;
47 END LOOP;
48 END IF;
49 END;
50 /
Procedure created.
测试:
SQL> EXEC p_grant('SCOTT', 'MIKE');
grant execute on SCOTT.F_TEST to MIKE
GRANT SELECT ON SCOTT.CALENDAR TO MIKE
grant execute on SCOTT.EXPORTTABLECONTENT to MIKE
<snip>
GRANT SELECT ON SCOTT.SALGRADE TO MIKE
GRANT SELECT ON SCOTT.LINKS TO MIKE
PL/SQL procedure successfully completed.
这是一个 PL/SQL 匿名块,因此您需要使用 PL/SQL 变量和绑定替换。试试这个:
DECLARE
user_exists NUMBER;
l_user VARCHAR2(30);
l_owner VARCHAR2(30);
BEGIN
l_user := 'USER1';
l_owner := 'USER2';
SELECT COUNT(*) INTO user_exists FROM ALL_USERS WHERE USERNAME = l_user;
IF user_exists > 0 THEN
FOR obj IN (SELECT object_name, object_type
FROM all_objects
WHERE owner = l_owner
AND object_type IN ('TABLE', 'VIEW', 'PROCEDURE', 'FUNCTION', 'PACKAGE'))
LOOP
IF obj.object_type IN ('TABLE', 'VIEW') THEN
EXECUTE IMMEDIATE 'GRANT SELECT ON :1 TO :2' USING obj.owner||'.'||obj.object_name, l_user;
ELSIF obj.object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE') THEN
EXECUTE IMMEDIATE 'GRANT EXECUTE ON :1 TO :2' USING obj.owner||'.'||obj.object_name, l_user;
END IF;
END LOOP;
END IF;
END;
当 table 为“flyway_schema_history”时,脚本将在授予对象 select 时失败...我不知道为什么会这样,但一种解决方案是跳过 table.
这是更新后的工作脚本:
DECLARE
user_exists NUMBER;
BEGIN
SELECT COUNT(*) INTO user_exists FROM ALL_USERS WHERE USERNAME = '${user}';
IF user_exists > 0 THEN
FOR obj IN (SELECT object_name, object_type
FROM all_objects
WHERE owner = '${owner}'
AND object_type IN ('TABLE', 'VIEW', 'PROCEDURE', 'FUNCTION', 'PACKAGE')
AND object_name NOT LIKE 'flyway_schema_history')
LOOP
IF obj.object_type IN ('TABLE', 'VIEW') THEN
EXECUTE IMMEDIATE 'GRANT SELECT ON ${owner}.' || obj.object_name ||
' TO ${user}';
ELSIF obj.object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE') THEN
EXECUTE IMMEDIATE 'GRANT EXECUTE ON ${owner}.' || obj.object_name || ' TO ${user}';
END IF;
END LOOP;
END IF;
END;
我尝试将对所有数据库对象的只读访问权限授予另一个可能不存在的用户。这就是我尝试这样做的方式:
DECLARE
user_exists NUMBER;
BEGIN
SELECT COUNT(*) INTO user_exists FROM ALL_USERS WHERE USERNAME = '${user}';
IF user_exists > 0 THEN
FOR obj IN (SELECT object_name, object_type
FROM all_objects
WHERE owner = '${owner}'
AND object_type IN ('TABLE', 'VIEW', 'PROCEDURE', 'FUNCTION', 'PACKAGE'))
LOOP
IF obj.object_type IN ('TABLE', 'VIEW') THEN
EXECUTE IMMEDIATE 'GRANT SELECT ON ${owner}.' || obj.object_name ||
' TO ${user}';
ELSIF obj.object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE') THEN
EXECUTE IMMEDIATE 'GRANT EXECUTE ON ${owner}.' || obj.object_name || ' TO ${user}';
END IF;
END LOOP;
END IF;
END;
脚本失败并显示以下消息:
Message : ORA-00942: table or view does not exist
ORA-06512: at line 16
ORA-06512: at line 16
我做错了什么?
除非我错了,所有 在你的代码中看起来像 ${something}
的东西都是错误的。
它应该做什么?您真的查询过 ALL_OBJECTS
并查看其中的内容吗?看起来好像你认为它们会自动被某种存在的东西所取代......呵呵,只是在你的想象中?
如果它是一个程序,那么您可以将所有者(授权人)和另一个用户(被授权人)作为参数传递。您编写的代码可以重复使用,其中大部分:
SQL> CREATE OR REPLACE PROCEDURE p_grant (par_owner IN VARCHAR2,
2 par_grantee IN VARCHAR2)
3 AS
4 user_exists NUMBER;
5 l_str VARCHAR2 (1000);
6 BEGIN
7 SELECT COUNT (*)
8 INTO user_exists
9 FROM all_users
10 WHERE username = DBMS_ASSERT.schema_name (par_grantee);
11
12 IF user_exists > 0
13 THEN
14 FOR obj IN (SELECT object_name, object_type
15 FROM all_objects
16 WHERE owner = DBMS_ASSERT.schema_name (par_owner)
17 AND object_type IN ('TABLE',
18 'VIEW',
19 'PROCEDURE',
20 'FUNCTION',
21 'PACKAGE')
22 AND STATUS = 'VALID')
23 LOOP
24 IF obj.object_type IN ('TABLE', 'VIEW')
25 THEN
26 l_str :=
27 'GRANT SELECT ON '
28 || par_owner
29 || '.'
30 || obj.object_name
31 || ' TO '
32 || par_grantee;
33 ELSIF obj.object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE')
34 THEN
35 l_str :=
36 ' grant execute on '
37 || par_owner
38 || '.'
39 || obj.object_name
40 || ' to '
41 || par_grantee;
42 END IF;
43
44 DBMS_OUTPUT.put_line (l_str);
45
46 EXECUTE IMMEDIATE l_str;
47 END LOOP;
48 END IF;
49 END;
50 /
Procedure created.
测试:
SQL> EXEC p_grant('SCOTT', 'MIKE');
grant execute on SCOTT.F_TEST to MIKE
GRANT SELECT ON SCOTT.CALENDAR TO MIKE
grant execute on SCOTT.EXPORTTABLECONTENT to MIKE
<snip>
GRANT SELECT ON SCOTT.SALGRADE TO MIKE
GRANT SELECT ON SCOTT.LINKS TO MIKE
PL/SQL procedure successfully completed.
这是一个 PL/SQL 匿名块,因此您需要使用 PL/SQL 变量和绑定替换。试试这个:
DECLARE
user_exists NUMBER;
l_user VARCHAR2(30);
l_owner VARCHAR2(30);
BEGIN
l_user := 'USER1';
l_owner := 'USER2';
SELECT COUNT(*) INTO user_exists FROM ALL_USERS WHERE USERNAME = l_user;
IF user_exists > 0 THEN
FOR obj IN (SELECT object_name, object_type
FROM all_objects
WHERE owner = l_owner
AND object_type IN ('TABLE', 'VIEW', 'PROCEDURE', 'FUNCTION', 'PACKAGE'))
LOOP
IF obj.object_type IN ('TABLE', 'VIEW') THEN
EXECUTE IMMEDIATE 'GRANT SELECT ON :1 TO :2' USING obj.owner||'.'||obj.object_name, l_user;
ELSIF obj.object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE') THEN
EXECUTE IMMEDIATE 'GRANT EXECUTE ON :1 TO :2' USING obj.owner||'.'||obj.object_name, l_user;
END IF;
END LOOP;
END IF;
END;
当 table 为“flyway_schema_history”时,脚本将在授予对象 select 时失败...我不知道为什么会这样,但一种解决方案是跳过 table.
这是更新后的工作脚本:
DECLARE
user_exists NUMBER;
BEGIN
SELECT COUNT(*) INTO user_exists FROM ALL_USERS WHERE USERNAME = '${user}';
IF user_exists > 0 THEN
FOR obj IN (SELECT object_name, object_type
FROM all_objects
WHERE owner = '${owner}'
AND object_type IN ('TABLE', 'VIEW', 'PROCEDURE', 'FUNCTION', 'PACKAGE')
AND object_name NOT LIKE 'flyway_schema_history')
LOOP
IF obj.object_type IN ('TABLE', 'VIEW') THEN
EXECUTE IMMEDIATE 'GRANT SELECT ON ${owner}.' || obj.object_name ||
' TO ${user}';
ELSIF obj.object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE') THEN
EXECUTE IMMEDIATE 'GRANT EXECUTE ON ${owner}.' || obj.object_name || ' TO ${user}';
END IF;
END LOOP;
END IF;
END;