如何向oracle中的其他用户授予对所有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

我尝试将对所有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
                  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”时的步骤