包对比java
- 包相当于java中的类,过程和函数相当于类的方法,变量相当于成员变量
- 包中的程序元素也分为公用元素(外包可用)和私用元素(同包)两种
- 当程序首次调用包内函数或过程时,ORACLE将整个包调入内存,当再次访问包内元素时,ORACLE直接从内存中读取
一个包由两个分开的部分组成:
- 包定义(PACKAGE):包定义部分声明包内数据类型、变量、常量、游标、子程序和异常错误处理等元素,这些元素为包的公有元素。
- 包主体(PACKAGE BODY):包主体则是包定义部分的具体实现,它定义了包定义部分所声明的游标和子程序,在包主体中还可以声明包的私有元素。
- 包定义和包主体分开编译,并作为两部分分开的对象存放在数据库字典中。
包定义的语法如下:
CREATE [OR REPLACE] PACKAGE package_name
{IS | AS}
[公有数据类型定义[公有数据类型定义]…]
[公有游标声明[公有游标声明]…]
[公有变量、常量声明[公有变量、常量声明]…]
[公有子程序声明[公有子程序声明]…]
END [package_name];
包体定义的语法如下:
CREATE [OR REPLACE] PACKAGE BODY package_name
{IS | AS}
[私有数据类型定义[私有数据类型定义]…]
[私有变量、常量声明[私有变量、常量声明]…]
[私有子程序声明和定义[私有子程序声明和定义]…]
[公有子程序定义[公有子程序定义]…]
BEGIN
PL/SQL 语句
END [package_name];
其中:在包主体定义公有程序时,它们必须与包定义中所声明子程序的格式完全一致
包的开发步骤:
- 将每个存储过程调式正确
- 用文本编辑软件将各个存储过程和函数集成在一起
- 按照包的定义要求将集成的文本的前面加上包定义
- 按照包的定义要求将集成的文本的前面加上包主体
- 使用开发工具进行调式
例:
1 CREATE OR REPLACE PACKAGE demo_pack 2 IS 3 DeptRec dept%ROWTYPE; 4 FUNCTION add_dept( 5 dept_no NUMBER, dept_name VARCHAR2, 6 location VARCHAR2) 7 RETURN NUMBER; 8 FUNCTION remove_dept(dept_no NUMBER) 9 RETURN NUMBER; 10 PROCEDURE query_dept(dept_no IN NUMBER); 11 END demo_pack; 12 13 CREATE OR REPLACE PACKAGE BODY demo_pack 14 IS 15 FUNCTION add_dept 16 (dept_no NUMBER, dept_name VARCHAR2, location VARCHAR2) 17 RETURN NUMBER 18 IS 19 empno_remaining EXCEPTION; 20 PRAGMA EXCEPTION_INIT(empno_remaining, -1); 21 /* -1 是违反唯一约束条件的错误代码 */ 22 BEGIN 23 INSERT INTO dept VALUES(dept_no, dept_name, location); 24 IF SQL%FOUND THEN 25 RETURN 1; 26 END IF; 27 EXCEPTION 28 WHEN empno_remaining THEN 29 RETURN 0; 30 WHEN OTHERS THEN 31 RETURN -1; 32 END add_dept; 33 34 PROCEDURE query_dept 35 (dept_no IN NUMBER) 36 IS 37 BEGIN 38 SELECT * INTO DeptRec FROM dept WHERE deptno=dept_no; 39 EXCEPTION 40 WHEN NO_DATA_FOUND THEN 41 DBMS_OUTPUT.PUT_LINE('数据库中没有编码为'||dept_no||'的部门'); 42 WHEN TOO_MANY_ROWS THEN 43 DBMS_OUTPUT.PUT_LINE('程序运行错误!请使用游标'); 44 WHEN OTHERS THEN 45 DBMS_OUTPUT.PUT_LINE(SQLCODE||'----'||SQLERRM); 46 END query_dept; 47 END demo_pack;
调用包
例:
1 DECLARE 2 Var NUMBER; 3 BEGIN 4 Var := demo_pack.add_dept(90,'Administration', 'Beijing'); 5 IF var =-1 THEN 6 DBMS_OUTPUT.PUT_LINE(SQLCODE||'----'||SQLERRM); 7 ELSIF var =0 THEN 8 DBMS_OUTPUT.PUT_LINE('该部门记录已经存在!'); 9 ELSE 10 DBMS_OUTPUT.PUT_LINE('添加记录成功!'); 11 Demo_pack.query_dept(90); 12 DBMS_OUTPUT.PUT_LINE(demo_pack.DeptRec.deptno||'---'|| 13 demo_pack.DeptRec.dname||'---'||demo_pack.DeptRec.loc); 14 var := demo_pack.remove_dept(90); 15 IF var =-1 THEN 16 DBMS_OUTPUT.PUT_LINE(SQLCODE||'----'||SQLERRM); 17 ELSIF var=0 THEN 18 DBMS_OUTPUT.PUT_LINE('该部门记录不存在!'); 19 ELSE 20 DBMS_OUTPUT.PUT_LINE('删除记录成功!'); 21 END IF; 22 END IF; 23 END;
可以使用 DROP PACKAGE 命令对不需要的包进行删除,语法如下:
例:DROP PACKAGE emp_package;
包所涉及到的数据字典视图:
DBA_SOURCE, USER_SOURCE, USER_ERRORS, DBA-OBJECTS