如何向oracle中的其他用户授予对所有DB对象的只读访问权限?
我尝试将对所有db对象的只读访问权授予可能不存在的另一个用户。我就是这样做的:如何向oracle中的其他用户授予对所有DB对象的只读访问权限?,oracle,oracle12c,Oracle,Oracle12c,我尝试将对所有db对象的只读访问权授予可能不存在的另一个用户。我就是这样做的: 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
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}
的东西都是错的
它应该做什么?你真的查询了所有的对象并看到里面有什么吗?看起来好像你认为他们会自动被存在的东西所取代。。。嗯,只是在你的想象中
如果是过程,则可以将所有者(授予者)和另一个用户(被授予者)作为参数传递。您编写的代码可以重用,其中大部分:
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.
SQL>execp_格兰特('SCOTT','MIKE');
授予MIKE执行SCOTT.F_测试的权利
将SCOTT.CALENDAR上的选择授予MIKE
将SCOTT.EXPORTTABLECONTENT上的执行授予MIKE
将SCOTT.SALGRADE上的SELECT授予MIKE
授予SCOTT上的SELECT。链接至MIKE
PL/SQL过程已成功完成。
这是一个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;
脚本将在授予选择对象时失败。。。当表格为“flyway\u schema\u history”时。我不知道发生这种情况的确切原因,但一个解决办法是跳过该表 以下是更新后的工作脚本:
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;
你是如何运行脚本的<代码>${user}和
${owner}
对于SQLPlus来说不是有效的替换语法。我使用flyway运行脚本${占位符}有效。我写了很多其他类似的脚本,没有问题。使用${something}在使用flyway时没有问题,我一直都在使用它。问题是,它将在执行即时命令“向BPSRedata_所有者授予选择权”时失败。| | obj.object|u name | | TO${user};当表格是“flyway\u schema\u history”时,是否碰巧是使用双引号创建的,所以它的名称真的是小写的?如果是这样,请再次用双引号将其括起来。否则,不知道。当我查看所有的_对象时,你是对的,它实际上是用小写字母写的。像往常一样,这是个坏主意。在Oracle中将任何名称括在双引号中,即使用${something}在使用flyway时没有问题,我一直都在使用它。问题是,它将在执行即时命令“向BPSRedata_所有者授予选择权”时失败。| | obj.object|u name | | TO${user};表格为“flyway\u schema\u history”时的步骤