当前位置:   article > 正文

Oracle进阶(六)包(Package)和包体_oracle创建包和包体

oracle创建包和包体

1、包(Package)概述

包(Package)是用来存储相关程序结构的对象,它存储于数据字典中。包由两部分组成:包规范(PACKAGE)和包体(PACKAGE BODY)。

包规范是包的说明部分,是对外的操作接口(类似java接口),对应用是可见的。

包体是包的代码和实现部分(类似java实现类),对应用来说是不可见的。

1.1 包说明

公有元素(PUBLIC)    在包头中说明,在包体中具体定义。在包外可见并可以访问,对整个应用的全过程有效。
私有元素(PRIVATE)  在包体的说明部分说明。只能被包内部的其他部分访问。
局部变量(LOCAL)     在过程或函数的说明部分说明。只能在定义变量的过程或函数中使用。

1.2 系统包

包名称描述
DBMS_OUTPUT在SQL*Plus环境下输出信息
DBMS_DDL编译过程函数和包
DBMS_SESSION改变用户的会话,初始化包等
DBMS_TRANSACTION控制数据库事务
DBMS_MAIL连接Oracle*Mail
DBMS_LOCK进行复杂的锁机制管理
DBMS_ALERT识别数据库事件告警
DBMS_PIPE通过管道在会话间传递信息
DBMS_JOB管理Oracle的作业
DBMS_LOB操纵大对象
DBMS_SQL执行动态SQL语句

2、基本语法

2.1 创建包和包体

  1. 1.创建包规范语法:
  2. CREATE [OR REPLACE] PACKAGE 包名 IS|AS
  3. --变量(VARIABLE)定义
  4. --常量(CONSTANT)定义
  5. --游标(CURSOR)定义
  6. --类型(TYPE)定义
  7. --函数定义
  8. FUNCTION 函数名 [(参数列表)] RETURN 返回类型;
  9. --存储过程定义
  10. PROCEDURE 存储过程名 [(参数列表)];
  11. 异常(EXCEPTION)
  12. END [包名];
  13. 2.创建包体语法:
  14. CREATE [OR REPLACE] PACKAGE BODY 包名 IS|AS
  15. --...
  16. --函数实现
  17. FUNCTION 函数名 [(参数列表)] RETURN 返回类型 IS|AS
  18. --函数实现内容
  19. --存储过程实现
  20. PROCEDURE 存储过程名 [(参数列表)] IS|AS
  21. --存储过程实现内容
  22. END [包名];

2.2 其它语法

  1. --1 删除包规范
  2. DROP PACKAGE 包规范名
  3. --2 删除包体
  4. DROP PACKAGE BODY 包体名
  5. --3 重新编译包头
  6. ALTER PACKAGE 包名 COMPILE PACKAGE
  7. --4 重新编译包体
  8. ALTER PACKAGE 包名 COMPILE PACKAGE BODY

2.3 注意要点

1 包说明和包体必须有相同的名字
2 包的开始没有BEGIN语句,与存储过程和函数不同。
3 在包的说明部分定义函数和过程的名称和参数,具体实现在包体中定义。
4 在包内声明常量、变量、类型定义、异常、及游标时不使用DECLARE。
5 包内的过程和函数的定义不要CREATE OR REPLACE语句。
6 包定义和包体两者分离。
7 只有当包头编辑成功后才能编辑包体。
8 函数名与过程名须和包头中的函数过程一样。

3、包的应用

以下所涉及的表,请查看Oracle进阶(三)常用函数的附表。

3.1 包创建

  1. CREATE OR REPLACE PACKAGE EMP_PK
  2. --包定义部分
  3. IS
  4. --公有变量:员工人数
  5. V_EMP_COUNT NUMBER(5);
  6. --公有过程:初始化数据
  7. PROCEDURE INIT(P_MAX NUMBER,P_MIN NUMBER);
  8. --公有过程:显示员工列表
  9. PROCEDURE LIST_EMP;
  10. --公有过程:新增员工
  11. PROCEDURE INSERT_EMP(P_EMPNO NUMBER,P_ENAME VARCHAR2,P_JOB VARCHAR2,P_SAL NUMBER);
  12. --公有过程:删除员工
  13. PROCEDURE DELETE_EMP(P_EMPNO NUMBER);
  14. --公有过程:修改员工工资
  15. PROCEDURE CHANGE_EMP_SAL(P_EMPNO NUMBER,P_SAL NUMBER);
  16. END EMP_PK;
  17. /
  18. CREATE OR REPLACE PACKAGE BODY EMP_PK
  19. --包体部分
  20. IS
  21. --私有变量:输出信息
  22. V_MESSAGE VARCHAR2(50);
  23. --私有变量:可修改工资上限
  24. V_MAX_SAL NUMBER(7);
  25. --私有变量:可修改工资下限
  26. V_MIN_SAL NUMBER(7);
  27. --私有函数:判断员工是否存在
  28. FUNCTION EXIST_EMP(P_EMPNO NUMBER) RETURN BOOLEAN;
  29. --私有过程:显示信息
  30. PROCEDURE SHOW_MESSAGE;
  31. --INIT
  32. PROCEDURE INIT(P_MAX NUMBER,P_MIN NUMBER)
  33. IS
  34. BEGIN
  35. SELECT COUNT(*) INTO V_EMP_COUNT FROM EMP;
  36. V_MAX_SAL:=P_MAX;
  37. V_MIN_SAL:=P_MIN;
  38. V_MESSAGE:='初始化数据已完成!';
  39. SHOW_MESSAGE;
  40. END INIT;
  41. --LIST_EMP
  42. PROCEDURE LIST_EMP
  43. IS
  44. BEGIN
  45. DBMS_OUTPUT.PUT_LINE('姓名 职务 工资');
  46. FOR EMP_REC IN (SELECT ENAME,JOB,SAL FROM EMP)
  47. LOOP
  48. DBMS_OUTPUT.PUT_LINE(RPAD(EMP_REC.ENAME,10,' ')||RPAD(EMP_REC.JOB,10,' ')||TO_CHAR(EMP_REC.SAL));
  49. END LOOP;
  50. DBMS_OUTPUT.PUT_LINE('员工总人数'|| V_EMP_COUNT);
  51. END LIST_EMP;
  52. --INSERT_EMP
  53. PROCEDURE INSERT_EMP(P_EMPNO NUMBER,P_ENAME VARCHAR2,P_JOB VARCHAR2,P_SAL NUMBER)
  54. IS
  55. BEGIN
  56. IF NOT EXIST_EMP(P_EMPNO) THEN
  57. INSERT INTO EMP(EMPNO,ENAME,JOB,SAL)VALUES(P_EMPNO,P_ENAME,P_JOB,P_SAL);
  58. COMMIT;
  59. V_EMP_COUNT:=V_EMP_COUNT+1;
  60. V_MESSAGE:='员工'||P_EMPNO||'已新增!';
  61. ELSE
  62. V_MESSAGE:='员工'||P_EMPNO||'已存在,不能新增!';
  63. END IF;
  64. SHOW_MESSAGE;
  65. EXCEPTION
  66. WHEN OTHERS THEN
  67. V_MESSAGE:='员工'||P_EMPNO||'新增失败!';
  68. SHOW_MESSAGE;
  69. END INSERT_EMP;
  70. --DELETE_EMP
  71. PROCEDURE DELETE_EMP(P_EMPNO NUMBER)
  72. IS
  73. BEGIN
  74. IF EXIST_EMP(P_EMPNO) THEN
  75. DELETE FROM EMP WHERE EMPNO=P_EMPNO;
  76. COMMIT;
  77. V_EMP_COUNT:=V_EMP_COUNT-1;
  78. V_MESSAGE:='员工'||P_EMPNO||'已删除!';
  79. ELSE
  80. V_MESSAGE:='员工'||P_EMPNO||'不存在,不能删除!';
  81. END IF;
  82. SHOW_MESSAGE;
  83. EXCEPTION
  84. WHEN OTHERS THEN
  85. V_MESSAGE:='员工'||P_EMPNO||'删除失败!';
  86. SHOW_MESSAGE;
  87. END DELETE_EMP;
  88. --CHANGE_EMP_SAL
  89. PROCEDURE CHANGE_EMP_SAL(P_EMPNO NUMBER,P_SAL NUMBER)
  90. IS
  91. BEGIN
  92. IF (P_SAL>V_MAX_SAL OR P_SAL<V_MIN_SAL) THEN
  93. V_MESSAGE:='工资超出修改范围!';
  94. ELSIF NOT EXIST_EMP(P_EMPNO) THEN
  95. V_MESSAGE:='员工'||P_EMPNO||'不存在,不能修改工资!';
  96. ELSE
  97. UPDATE EMP SET SAL=P_SAL WHERE EMPNO=P_EMPNO;
  98. COMMIT;
  99. V_MESSAGE:='员工'||P_EMPNO||'工资已经修改!';
  100. END IF;
  101. SHOW_MESSAGE;
  102. EXCEPTION
  103. WHEN OTHERS THEN
  104. V_MESSAGE:='员工'||P_EMPNO||'工资修改失败!';
  105. SHOW_MESSAGE;
  106. END CHANGE_EMP_SAL;
  107. --SHOW_MESSAGE
  108. PROCEDURE SHOW_MESSAGE
  109. IS
  110. BEGIN
  111. DBMS_OUTPUT.PUT_LINE('提示信息:'||V_MESSAGE);
  112. END SHOW_MESSAGE;
  113. --EXIST_EMP
  114. FUNCTION EXIST_EMP(P_EMPNO NUMBER)
  115. RETURN BOOLEAN
  116. IS
  117. --局部变量:员工数量
  118. V_NUM NUMBER;
  119. BEGIN
  120. SELECT COUNT(*) INTO V_NUM FROM EMP WHERE EMPNO=P_EMPNO;
  121. IF V_NUM=1 THEN
  122. RETURN TRUE;
  123. ELSE
  124. RETURN FALSE;
  125. END IF;
  126. END EXIST_EMP;
  127. END EMP_PK;

3.2 包调用

  1. --调用包
  2. --1 初始化
  3. BEGIN
  4. EMP_PK.INIT(P_MAX => 200,
  5. P_MIN => 100);
  6. END;
  7. --2 员工列表
  8. CALL EMP_PK.LIST_EMP();
  9. --3 新增员工
  10. CALL EMP_PK.INSERT_EMP(2021,'一二山人','YESR',10000);
  11. --4 查看员工人数
  12. BEGIN
  13. DBMS_OUTPUT.PUT_LINE(EMP_PK.V_EMP_COUNT);
  14. END;
  15. --5 删除员工
  16. CALL EMP_PK.DELETE_EMP(2021);
  17. --6 修改工资
  18. CALL EMP_PK.CHANGE_EMP_SAL(7900,150);
  19. --7 授权其他用户调用包
  20. GRANT EXECUTE ON EMP_PK TO SYS;
  21. --8 其它用户SYS调用包
  22. CALL SCOTT.EMP_PK.INIT(400,300);

4、包的进阶

4.1 包重载创建

  1. CREATE OR REPLACE PACKAGE EMP_OVERLOAD_PK IS
  2. --过程:新增部门
  3. PROCEDURE INSERT_DEPT (
  4. P_DEPTNO DEPT.DEPTNO%TYPE, --部门编号
  5. P_DNAME DEPT.DNAME%TYPE, --部门名称
  6. P_LOC DEPT.LOC%TYPE --位置
  7. );
  8. --过程:新增部门(重载)
  9. PROCEDURE INSERT_DEPT (
  10. P_DEPTNO DEPT.DEPTNO%TYPE, --部门编号
  11. P_DNAME DEPT.DNAME%TYPE --部门名称
  12. );
  13. --函数:获取员工加薪
  14. FUNCTION GET_ADDSALARY (P_EMPNO EMP.EMPNO%TYPE)
  15. RETURN NUMBER;
  16. --函数:获取员工加薪(重载)
  17. FUNCTION GET_ADDSALARY (P_ENAME EMP.ENAME%TYPE)
  18. RETURN NUMBER;
  19. END EMP_OVERLOAD_PK;
  20. /
  21. CREATE OR REPLACE PACKAGE BODY EMP_OVERLOAD_PK
  22. IS
  23. FUNCTION EXIST_DEPT(P_DEPTNO DEPT.DEPTNO%TYPE) RETURN NUMBER;
  24. --INSERT_DEPT
  25. PROCEDURE INSERT_DEPT (
  26. P_DEPTNO DEPT.DEPTNO%TYPE,
  27. P_DNAME DEPT.DNAME%TYPE,
  28. P_LOC DEPT.LOC%TYPE
  29. )
  30. AS
  31. BEGIN
  32. IF EXIST_DEPT(P_DEPTNO) > 0 --如果部门存在
  33. THEN --抛出异常
  34. RAISE_APPLICATION_ERROR (-2021, '出现了相同的员工记录');
  35. END IF;
  36. INSERT INTO DEPT(DEPTNO, DNAME, LOC)
  37. VALUES (P_DEPTNO, P_DNAME, P_LOC);--新增
  38. COMMIT;
  39. END INSERT_DEPT;
  40. --INSERT_DEPT(重载)
  41. PROCEDURE INSERT_DEPT (
  42. P_DEPTNO DEPT.DEPTNO%TYPE,
  43. P_DNAME DEPT.DNAME%TYPE
  44. )
  45. AS
  46. BEGIN
  47. IF EXIST_DEPT(P_DEPTNO) > 0 --如果部门存在
  48. THEN --抛出异常
  49. RAISE_APPLICATION_ERROR (-2022, '出现了相同的员工记录');
  50. END IF;
  51. INSERT INTO DEPT(DEPTNO, DNAME, LOC)
  52. VALUES (P_DEPTNO, P_DNAME, '广州天河区');--新增记录
  53. COMMIT;
  54. END INSERT_DEPT;
  55. --GET_ADDSALARY
  56. FUNCTION GET_ADDSALARY (P_EMPNO EMP.EMPNO%TYPE)
  57. RETURN NUMBER
  58. IS
  59. V_JOB EMP.JOB%TYPE;
  60. V_SAL EMP.SAL%TYPE;
  61. V_SALARYRATIO NUMBER (10, 2);--调薪比率
  62. BEGIN
  63. --获取员工表中的薪资信息
  64. SELECT JOB, SAL INTO V_JOB, V_SAL FROM EMP WHERE EMPNO = P_EMPNO;
  65. CASE V_JOB
  66. WHEN 'CLERK' THEN
  67. V_SALARYRATIO := 1.05;
  68. WHEN 'SALESMAN' THEN
  69. V_SALARYRATIO := 1.1;
  70. WHEN 'MANAGER' THEN
  71. V_SALARYRATIO := 1.2;
  72. ELSE
  73. V_SALARYRATIO := 1;
  74. END CASE;
  75. IF V_SALARYRATIO <> 1
  76. THEN
  77. RETURN ROUND(V_SAL * V_SALARYRATIO,2);
  78. ELSE
  79. RETURN V_SAL;
  80. END IF;
  81. EXCEPTION
  82. WHEN NO_DATA_FOUND THEN
  83. RETURN 0;
  84. END GET_ADDSALARY;
  85. --GET_ADDSALARY(重载)
  86. FUNCTION GET_ADDSALARY (P_ENAME EMP.ENAME%TYPE)
  87. RETURN NUMBER
  88. IS
  89. V_JOB EMP.JOB%TYPE;
  90. V_SAL EMP.SAL%TYPE;
  91. V_SALARYRATIO NUMBER (10, 2);--调薪比率
  92. BEGIN
  93. --获取员工表中的薪资信息
  94. SELECT JOB, SAL INTO V_JOB, V_SAL FROM EMP WHERE ENAME = P_ENAME;
  95. CASE V_JOB
  96. WHEN 'CLERK' THEN
  97. V_SALARYRATIO := 1.05;
  98. WHEN 'SALESMAN' THEN
  99. V_SALARYRATIO := 1.1;
  100. WHEN 'MANAGER' THEN
  101. V_SALARYRATIO := 1.2;
  102. ELSE
  103. V_SALARYRATIO := 1;
  104. END CASE;
  105. IF V_SALARYRATIO <> 1
  106. THEN
  107. RETURN ROUND(V_SAL * V_SALARYRATIO,2);
  108. ELSE
  109. RETURN V_SAL;
  110. END IF;
  111. EXCEPTION
  112. WHEN NO_DATA_FOUND THEN
  113. RETURN 0;
  114. END GET_ADDSALARY;
  115. --私有函数:部门是否存在
  116. FUNCTION EXIST_DEPT(P_DEPTNO DEPT.DEPTNO%TYPE) RETURN NUMBER
  117. AS
  118. V_COUNT NUMBER(2);
  119. BEGIN
  120. SELECT COUNT(*) INTO V_COUNT FROM DEPT WHERE DEPTNO=P_DEPTNO;
  121. RETURN V_COUNT;
  122. END;
  123. END EMP_OVERLOAD_PK;

4.2 包重载调用

  1. --调用
  2. BEGIN
  3. EMP_OVERLOAD_PK.INSERT_DEPT(50,,);
  4. END
  5. --重载过程
  6. BEGIN
  7. EMP_OVERLOAD_PK.INSERT_DEPT(P_DEPTNO => 50,
  8. P_DNAME =>'交付二部',
  9. P_LOC => '海珠区');
  10. END;
  11. --过程
  12. BEGIN
  13. EMP_OVERLOAD_PK.INSERT_DEPT(P_DEPTNO => 60,
  14. P_DNAME =>'交付一部');
  15. END;
  16. ----重载函数
  17. DECLARE
  18. V_SAL NUMBER(10,2);
  19. BEGIN
  20. V_SAL:=EMP_OVERLOAD_PK.GET_ADDSALARY(7369);
  21. DBMS_OUTPUT.PUT_LINE('获取员工加薪'|| V_SAL);
  22. END;
  23. --函数
  24. DECLARE
  25. V_SAL NUMBER(10,2);
  26. BEGIN
  27. V_SAL:=EMP_OVERLOAD_PK.GET_ADDSALARY('SMITH');
  28. DBMS_OUTPUT.PUT_LINE('获取员工加薪'|| V_SAL);
  29. END;

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/341663
推荐阅读
相关标签
  

闽ICP备14008679号