Article Directory
1 Overview
1. 包的概念
(1) 模块化的思想,用于分类管理过程(procedure)和函数(function)
(2) 类似于 Java、Python 等语言中的 类(class)
2. 包的组成(程序部署顺序:'先执行包头,再执行包体')
(1) 包头:package
(2) 包体:package body
3. 授权: grant execute on 属主.包名 to 用户1, 用户n;
4. 调用: '属主.包名.存储过程名()' 或 '属主.包名.方法名()'
5. 建议
(1) 数据库中所有的过程(procedure)和函数(function)都要用 package 进行封装:便于管理
(2) 单个的过程(procedure)和函数(function)建议不超过 3000 行
(3) 每个 package 在 create 时都要带上 '属主'(避免所处位置错误)
2 Example
Example of effect screenshot: user hr calls package in user scott to determine whether a table exists in scott
Baotou:
CREATE OR REPLACE PACKAGE scott.pkg_public_toolkit IS
PROCEDURE p_whether_table_exists(i_table_name IN sys.all_tab_comments.table_name%TYPE,
o_flag OUT VARCHAR2,
o_message OUT VARCHAR2);
FUNCTION f_whether_table_exists(i_table_name IN sys.all_tab_comments.table_name%TYPE)
RETURN VARCHAR2;
END pkg_public_toolkit;
/
GRANT EXECUTE ON scott.pkg_public_toolkit TO hr;
Package body:
CREATE OR REPLACE PACKAGE BODY scott.pkg_public_toolkit IS
-- *********************************************
-- 功能说明: 判断用户 scott 中是否存在表
-- 参数说明: i_table_name 表名
-- o_flag 程序执行标志,Y:成功,N:失败
-- o_message 程序执行的描述信息
-- 修改记录:create by yoyo 2020/10/14
-- *********************************************
PROCEDURE p_whether_table_exists(i_table_name IN sys.all_tab_comments.table_name%TYPE,
o_flag OUT VARCHAR2,
o_message OUT VARCHAR2) IS
v_count NUMBER(1);
BEGIN
-- 判断依据:用户 scott 中是否存在表
SELECT COUNT(1)
INTO v_count
FROM user_tab_comments ust
WHERE ust.table_name = upper(i_table_name);
-- 程序执行描述信息
IF v_count >= 1 THEN
o_message := '存在';
ELSE
o_message := '不存在';
END IF;
-- 程序执行标识
o_flag := 'Y';
EXCEPTION
WHEN OTHERS THEN
o_flag := 'N'; -- 执行失败
dbms_output.put_line(dbms_utility.format_error_backtrace); -- 报错的行号
dbms_output.put_line(SQLCODE || ' : ' || SQLERRM); -- 报错的编号及内容
END p_whether_table_exists;
-- *********************************************
-- 功能说明: 调用存储过程 p_whether_table_exists 的方法
-- 参数说明:i_empno 部门编号
-- 返回值: i_table_name 表名
-- 修改记录:create by yoyo 2020/10/14
-- *********************************************
FUNCTION f_whether_table_exists(i_table_name IN sys.all_tab_comments.table_name%TYPE)
RETURN VARCHAR2 IS
o_flag VARCHAR2(2);
o_message VARCHAR2(100);
BEGIN
p_whether_table_exists(i_table_name => i_table_name,
o_flag => o_flag,
o_message => o_message);
RETURN o_message;
END f_whether_table_exists;
END pkg_public_toolkit;
/
After the creation is complete, the location of Package can also be found in PL/SQL:
3 Please note
1. 授权完成,仅表示 '用户n' 能够 '执行' 该 pkg,
不能保证 '用户n' 能够查询该 pkg 中的 '对象(如:表)', 如图 3.1
2. package、procedure、function 声明时 is 和 as 的区别
(1) 在 package、procedure、function 及自定义类型 type 时,as 和 is 一样,没区别
(2) 在声明游标(cursor)时,只能使用 is 而不能使用 as
(3) 在创建视图(view)时,只能使用 as 而不能使用 is
3. 规范:package、procedure、function 在结束时的 end 后面都要带上对应的名字
只有匿名语句块的 end 后面才不带名字,如:
begin
pl/sql 语句;
end;
Figure 3.1: The user hr query table scott.emp reports an error
解决办法:授权
grant select on scott.emp to hr;
revoke select on scott.emp from hr; -- 回收权限。