Oracle 12c中增强的PL/SQL功能(3)

CREATE OR REPLACE PACKAGE BODY public_pkg
IS
  PROCEDURE do_only_this
  IS
  BEGIN
      private_pkg.do_this;
      private_pkg.do_that;
  END;
END;
/

CREATE OR REPLACE PACKAGE BODY
private_pkg
IS
  PROCEDURE do_this
  IS
  BEGIN
      DBMS_OUTPUT.put_line ('THIS');
  END;

PROCEDURE do_that
  IS
  BEGIN
      DBMS_OUTPUT.put_line ('THAT');
  END;
END;
/

现在可以毫无问题的运行这个公共包的过程:

BEGIN
  public_pkg.do_only_this;
END;
/
THIS
THAT

但是��果我试图在匿名块中调用私有包的子过程,出现以下错误:(呦吼!耍不了赖了!嗯哼,有意思!)

BEGIN
  private_pkg.do_this;
END;
/

ERROR at line 2:
ORA-06550: line 2, column 1:
PLS-00904: insufficient privilege to
access object PRIVATE_PKG
ORA-06550: line 2, column 1:
PL/SQL: Statement ignored

程序试图调用私有包的子程序,编译则会报同样的错误:

SQL> CREATE OR REPLACE PROCEDURE
use_private
  2  IS
  3  BEGIN
  4    private_pkg.do_this;
  5  END;
  6  /
Warning: Procedure created with
compilation errors.

SQL> SHOW ERRORS

Errors for PROCEDURE USE_PRIVATE:

LINE/COL ERROR
———————— ——————————————————————————
4/4      PL/SQL: Statement ignored
4/4      PLS-00904: insufficient
        privilege to access object
        PRIVATE_PKG

看好了,是“PLS”错误提示,这个问题将在编译期间即被捕捉。使用这个特性不会带来任何的运行时性能影响。
5. 将角色授权给程序单元
12c以前,一个定义者权限的程序单元(以AUTHID DEFINER定义或不指定)总是以单元所有者的权限执行。一个调用者权限程序单元(以AUTHID CURRENT_USER定义)总是以单元调用者的权限执行。
这种设置的一个结果是,如果一个程序需要被所有用户执行,那么该程序将被设置为定义者权限单元。这样一来将拥有定义者所有权限来执行程序单元,从安全角度来看不是很好。
自12c起,你可以将角色授权给PL/SQL包和模式级过程和函数。基于角色权限的程序单元使开发者更细致地分配相应的程序单元给调用者。
你现在可以定义一个调用者权限的程序单元,然后通过授权有限的权限给相应角色来补足调用者权限。
让我们来走查以下例子,展示如何授权角色给程序单元。假设HR模式包含departments和employees表,定义和填充数据如下:

CREATE TABLE departments
(
  department_id    INTEGER,
  department_name  VARCHAR2 (100),
  staff_freeze      CHAR (1)
)
/

BEGIN
  INSERT INTO departments
        VALUES (10, 'IT', 'Y');

INSERT INTO departments
        VALUES (20, 'HR', 'N');

COMMIT;
END;
/

CREATE TABLE employees
(
  employee_id    INTEGER,
  department_id  INTEGER,
  last_name      VARCHAR2 (100)
)
/

BEGIN
  DELETE FROM employees;

INSERT INTO employees
        VALUES (100, 10, 'Price');

INSERT INTO employees
        VALUES (101, 20, 'Sam');

INSERT INTO employees
        VALUES (102, 20, 'Joseph');
  INSERT INTO employees
        VALUES (103, 20, 'Smith');

COMMIT;
END;
/

并且假设SCOTT模式下仅包含employees表,定义和填充数据如下:

CREATE TABLE employees
(
  employee_id    INTEGER,
  department_id  INTEGER,
  last_name      VARCHAR2 (100)
)
/

BEGIN
  DELETE FROM employees;

INSERT INTO employees
        VALUES (100, 10, 'Price');

INSERT INTO employees
        VALUES (104, 20, 'Lakshmi');

INSERT INTO employees
        VALUES (105, 20, 'Silva');

INSERT INTO employees
        VALUES (106, 20, 'Ling');
  COMMIT;
END;
/

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/bd9976f65e0f095de14cb438f0a932d9.html