Oracle专题15之包

前端之家收集整理的这篇文章主要介绍了Oracle专题15之包前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

1、包的概述

a、什么是包?

  • 包是一组相关过程、函数、变量、常量和游标等PL/sql程序设计元素的组合。

b、包的特点?

  • 它具有面向对象程序设计语言的特点,是对PL/sql程序设计元素(过程、函数、变量等)的封装。
  • 它使程序设计模块化。

c、包中的程序元素

  • 包中的程序元素分为两种:公用元素(公用组件)、私用元素(私用组件)。

e、包的组成

  • 一个包由两个分开的部分组成:
  • 包规范(包定义):用于定义包的公用组件,包括常量、变量、游标、过程和函数等。
  • 包体(包主体):用于实现包规范所定义的公用过程和函数。包体不仅可用于实现公用过程和函数,而且还可以定义包的私有组件(变量、游标、过程、函数等)。

f、简单代码示例

  • 创建包规范和包体的示例代码
  1. --创建包规范
  2. CREATE OR REPLACE PACKAGE first_package
  3. IS
  4. v_no emp.deptno%TYPE := 10;
  5. --过期
  6. PROCEDURE query_emp(v_deptno IN NUMBER DEFAULT v_no,v_avgsal OUT NUMBER,v_cnt OUT NUMBER);
  7. END first_package;
  8. --创建包体
  9. CREATE OR REPLACE PACKAGE BODY first_package
  10. IS
  11. PROCEDURE query_emp(v_deptno IN NUMBER DEFAULT v_no,v_avgsal) OUT NUMBER,v_cnt OUT NUMBER)
  12. IS
  13. BEGIN
  14. SELECT avg(sal),count(*) INTO v_avgsal,v_cnt FROM emp WHERE deptno = v_deptno;
  15. EXCEPTION
  16. WHEN NO_DATA_FOUND THEN
  17. dbms_output.put_line('没有此部门');
  18. WHEN OTHERS THEN
  19. dbms_output.put_line(sqlERRM);
  20. END;
  21. END first_package;
  22. ```
  23. - 调用包中的存储过程:
  1. DECLARE
  2. v_avgsal NUMBER;
  3. v_cnt NUMBER;
  4. BEGIN
  5. first_package.query_emp(20,v_avgsal,v_cnt);
  6. DBMS_OUTPUT.put_line('平均工资:' || v_avgsal);
  7. DBMS_OUTPUT.put_line('总人数:' || v_cnt);
  8. END;
  1. # 2、包的创建
  2. ## a、创建包规范
  3. - 语法格式如下:

CREATE [OR REPLACE] PACKAGE package_name IS | AS -- 定义公用常量、变量、游标、过程、函数等 END [package_name];

  1. - 示例代码
  2. ```
  3. CREATE OR REPLACE PACKAGE emp_package
  4. IS
  5. --添加员工信息的存储过程
  6. PROCEDURE add_emp_proc
  7. (v_empno IN emp.empno%TYPE,v_ename IN emp.ename%TYPE,v_sal IN emp.sal%TYPE,v_deptno IN emp.deptno%TYPE);
  8.  
  9. --删除员工信息的存储过程
  10. PROCEDURE del_emp_proc
  11. (v_empno IN emp.empno%TYPE);
  12. END emp_package;

b、创建包体

  • 语法格式如下:
  1. CREATE [OR REPLACE] PACKAGE BODY package_name
  2. IS | AS
  3. --定义私有常量、变量、游标、过程和函数
  4. --实现公用过程和函数
  5. END [package_name];
  1. CREATE OR REPLACE PACKAGE BODY emp_package
  2. IS
  3. --添加员工信息的存储过程
  4. PROCEDURE add_emp_proc
  5. (v_empno IN emp.empno%TYPE,v_deptno IN emp.deptno%TYPE)
  6. IS
  7. e_2291 EXCEPTION;
  8. PRAGMA EXCEPTION_INIT(e_2291,-2291);
  9. BEGIN
  10. INSERT INTO emp(empno,ename,sal,deptno) VALUES(v_empno,v_ename,v_sal,v_deptno);
  11. EXCEPTION
  12. WHEN DUP_VAL_ON_INDEX THEN
  13. RAISE_APPLICATION_ERROR(-20001,'员工号不能重复');
  14. WHEN e_2291 THEN
  15. RAISE_APPLICATION_ERROR(-20002,'部门号不存在');
  16. END;
  17.  
  18. --删除员工信息的存储过程
  19. PROCEDURE del_emp_proc
  20. (v_empno IN emp.empno%TYPE)
  21. IS
  22. BEGIN
  23. --根据员工号删除指定的员工信息
  24. DELETE FROM emp WHERE empno = v_empno;
  25. --判断是否删除成功
  26. IF sql%NOTFOUND THEN
  27. RAISE_APPLICATION_ERROR(-20009,'指定删除的员工不存在');
  28. ELSE
  29. DBMS_OUTPUT.PUT_line('删除成功');
  30. END IF;
  31. END;
  32. END emp_package;

c、包创建的过程案例代码

  • 根据员工号查询工资,如果工资小于等于3000,工资涨500。
  1. --创建包规范
  2. CREATE OR REPLACE PACKAGE emp_sal_pkg
  3. IS
  4. FUNCTION get_sal(eno NUMBER) RETURN NUMBER;
  5.  
  6. PROCEDURE upd_sal(eno NUMBER,salary NUMBER);
  7. END emp_sal_pkg;
  8.  
  9. --包体
  10. CREATE OR REPLACE PACKAGE BODY emp_sal_pkg
  11. IS
  12. FUNCTION get_sal(eno NUMBER) RETURN NUMBER
  13. IS
  14. v_sal emp.sal%TYPE := 0;
  15. BEGIN
  16. SELECT sal INTO v_sal FROM emp WHERE empno = eno;
  17. RETURN v_sal;
  18. EXCEPTION
  19. WHEN NO_DATA_FOUND THEN
  20. RAISE_APPLICATION_ERROR(-20010,'此员工号不存在');
  21. END;
  22.  
  23. PROCEDURE upd_sal(eno NUMBER,salary NUMBER)
  24. IS
  25. BEGIN
  26. IF salary <=3000 THEN
  27. UPDATE emp SET sal = sal + 500 WHERE empno = eno;
  28. END IF;
  29. END;
  30. END emp_sal_pkg;

3、包的调用删除

a、包的调用

  • 对包内共有元素(公用组件)的调用格式为:包名.元素名称(组件名称
  • 例如:emp_package.del_emp_proc();

b、 包的调用示例1

  • 调用emp_package包下添加员工信息的存储过程。(在本专题的第2节包的创建,已经在Oracle数据库中创建emp_package包规范和包体)
  1. DECLARE
  2. v_empno emp.empno%TYPE := &empno;
  3. v_ename emp.ename%TYPE := '&name';
  4. v_sal emp.sal%TYPE := &salary;
  5. v_deptno emp.deptno%TYPE := &deptno;
  6. e_dup_val EXCEPTION;
  7. e_no_dept EXCEPTION;
  8.  
  9. PRAGMA EXCEPTION_INIT(e_dup_val,-20001);
  10. PRAGMA EXCEPTION_INIT(e_no_dept,-20002);
  11. BEGIN
  12. emp_package.add_emp_proc(v_empno,v_deptno);
  13. COMMIT;
  14. EXCEPTION
  15. WHEN e_dup_val THEN
  16. DBMS_OUTPUT.put_line(sqlERRM);
  17. WHEN e_no_dept THEN
  18. DBMS_OUTPUT.put_line(sqlERRM);
  19. ROLLBACK;
  20. END;

b、包的调用示例2

  • 调用emp_package包下删除员工信息的存储过程。(在本专题的第2节包的创建,已经在Oracle数据库中创建emp_package包规范和包体)
  1. DECLARE
  2. v_empno emp.empno%TYPE := &empno;
  3. e_no_emp EXCEPTION;
  4. PRAGMA EXCEPTION_INIT(e_no_emp,-20009);
  5. BEGIN
  6. emp_package.del_emp_proc(v_empno);
  7. COMMIT;
  8. EXCEPTION
  9. WHEN e_no_emp THEN
  10. DBMS_OUTPUT.put_line(sqlERRM);
  11. ROLLBACK;
  12. END;

c、包的调用示例3

  • 调用emp_sal_pkg包下的过程和函数:(在本专题的第2节包的创建,已经在Oracle数据库中创建emp_sal_pkg包规范和包体) 1、调用根据员工号返回员工工资的函数 2、调用更新满足条件的员工工资的过程
  1. DECLARE
  2. v_empno emp.empno%TYPE := &empno;
  3. v_salary emp.sal%TYPE;
  4. e_no_emp EXCEPTION;
  5. PRAGMA EXCEPTION_INIT(e_no_emp,-20010);
  6. BEGIN
  7. v_salary := emp_sal_pkg.get_sal(v_empno);
  8. emp_sal_pkg.upd_sal(v_empno,v_salary);
  9. COMMIT;
  10. EXCEPTION
  11. WHEN e_no_emp THEN
  12. DBMS_OUTPUT.put_line(sqlERRM);
  13. END;

d、如何在sqlPlus窗口中进行包的调用

  • 示例1:在sqlPlus窗口中进行emp_sal_pkg包的调用查询员工的工资信息:
  1. sql> VAR v_empno NUMBER
  2. sql> EXEC :v_empno := &no
  3.  
  4. PL/sql procedure successfully completed
  5.  
  6. v_empno
  7. ---------
  8. 1234
  9.  
  10. sql> VAR v_salary NUMBER
  11. sql> EXEC :v_salary := emp_sal_pkg.get_sal(:v_empno)
  12. begin :v_salary := emp_sal_pkg.get_sal(:v_empno); end;
  13.  
  14. ORA-20010: 此员工号不存在
  15. ORA-06512: "SCOTT.EMP_SAL_PKG",line 11
  16. ORA-06512: line 1
  17. v_salary
  18. ---------
  19. v_empno
  20. ---------
  21. 1234
  • 示例2:在sqlPlus窗口中进行emp_sal_pkg包的调用,更新员工的工资信息:(变量v_empno已经在示例1中定义)
  1. sql> EXEC :v_empno := &no
  2.  
  3. PL/sql procedure successfully completed
  4.  
  5. v_empno
  6. ---------
  7. 7369
  8.  
  9. sql> EXEC :v_salary := emp_sal_pkg.get_sal(:v_empno)
  10.  
  11. PL/sql procedure successfully completed
  12.  
  13. v_salary
  14. ---------
  15. 800
  16. v_empno
  17. ---------
  18. 7369
  19.  
  20. sql> EXEC emp_sal_pkg.upd_sal(:v_empno,:v_salary)
  21.  
  22. PL/sql procedure successfully completed
  23.  
  24. v_empno
  25. ---------
  26. 7369
  27. v_salary
  28. ---------
  29. 800
  30.  
  31. sql> SELECT ename,sal from emp WHERE empno = 7369;
  32.  
  33. ENAME SAL
  34. ---------- ---------
  35. G_EASON 1300.00
  • sqlPlus环境中,可以使用 [VAR 变量名 变量类型]命令定义变量。

e、包的删除

  • 可以使用DROP PACKAGE命令对不需要的包进行删除,语法如下:
  1. DROP PACKAGE [BODY] [user.] package_name;

4、子程序重载

a、什么是子程序重载?

  • 所谓重载是指两个或者多个子程序有相同的名称,但是拥有不同的参数变量、参数顺序或者参数数据类型。

b、示例代码

  • 示例:1、根据员工号或者员工姓名获取员工信息;2、根据员工号或者员工姓名删除员工的信息。
  1. --创建包规范
  2. CREATE OR REPLACE PACKAGE overload_pkg
  3. IS
  4. FUNCTION get_info(eno NUMBER) RETURN emp%ROWTYPE;
  5. FUNCTION get_info(name VARCHAR) RETURN emp%ROWTYPE;
  6.  
  7. PROCEDURE del_emp(eno NUMBER);
  8. PROCEDURE del_emp(name VARCHAR);
  9. END;
  10. --创建包体
  11. CREATE OR REPLACE PACKAGE BODY overload_pkg
  12. IS
  13. FUNCTION get_info(eno NUMBER) RETURN emp%ROWTYPE
  14. IS
  15. emp_record emp%ROWTYPE;
  16. BEGIN
  17. SELECT * INTO emp_record FROM emp WHERE empno = eno;
  18. RETURN emp_record;
  19. EXCEPTION
  20. WHEN NO_DATA_FOUND THEN
  21. RAISE_APPLICATION_ERROR(-20020,'不存在此员工');
  22. END;
  23.  
  24. FUNCTION get_info (name VARCHAR) RETURN emp%ROWTYPE
  25. IS
  26. emp_record emp%ROWTYPE;
  27. BEGIN
  28. SELECT * INTO emp_record FROM emp WHERE ename= name;
  29. RETURN emp_record;
  30. EXCEPTION
  31. WHEN NO_DATA_FOUND THEN
  32. RAISE_APPLICATION_ERROR(-20020,'不存在此员工');
  33. END;
  34.  
  35. PROCEDURE del_emp(eno NUMBER)
  36. IS
  37. BEGIN
  38. DELETE FROM emp WHERE empno = eno;
  39. IF sql%NOTFOUND THEN
  40. RAISE_APPLICATION_ERROR(-20020,'不存在此员工');
  41. END IF;
  42. END;
  43.  
  44. PROCEDURE del_emp(name VARCHAR)
  45. IS
  46. BEGIN
  47. DELETE FROM emp WHERE ename = name;
  48. IF sql%NOTFOUND THEN
  49. RAISE_APPLICATION_ERROR(-20020,'不存在此员工');
  50. END IF;
  51. END;
  52. END overload_pkg;
  • overload_pkg包的调用示例:
  1. --根据员工号查询员工信息
  2. DECLARE
  3. emp_record emp%rowtype;
  4. e_no_emp EXCEPTION;
  5. PRAGMA EXCEPTION_INIT(e_no_emp,-20020);
  6. BEGIN
  7. emp_record := overload_pkg.get_info(&no);
  8. DBMS_OUTPUT.put_line('员工号:' || emp_record.empno || ',姓名:' || emp_record.ename || ',工资:' ||
  9. emp_record.sal);
  10. EXCEPTION
  11. WHEN e_no_emp THEN
  12. DBMS_OUTPUT.put_line(sqlERRM);
  13. END;
  1. --根据员工姓名查询员工信息
  2. DECLARE
  3. emp_record emp%rowtype;
  4. e_no_emp EXCEPTION;
  5. PRAGMA EXCEPTION_INIT(e_no_emp,-20020);
  6. BEGIN
  7. emp_record := overload_pkg.get_info('&ename');
  8. DBMS_OUTPUT.put_line('员工号:' || emp_record.empno || ',姓名:' || emp_record.ename || ',工资:' ||
  9. emp_record.sal);
  10. EXCEPTION
  11. WHEN e_no_emp THEN
  12. DBMS_OUTPUT.put_line(sqlERRM);
  13. END;
  1. --根据员工号删除员工信息
  2. DECLARE
  3. e_no_emp EXCEPTION;
  4. PRAGMA EXCEPTION_INIT(e_no_emp,-20020);
  5. BEGIN
  6. overload_pkg.del_emp(&no);
  7. COMMIT;
  8. EXCEPTION
  9. WHEN e_no_emp THEN
  10. DBMS_OUTPUT.put_line(sqlERRM);
  11. ROLLBACK;
  12. END;
  1. --根据员工姓名删除员工信息
  2. DECLARE
  3. e_no_emp EXCEPTION;
  4. PRAGMA EXCEPTION_INIT(e_no_emp,-20020);
  5. BEGIN
  6. overload_pkg.del_emp('&ename');
  7. COMMIT;
  8. EXCEPTION
  9. WHEN e_no_emp THEN
  10. DBMS_OUTPUT.put_line(sqlERRM);
  11. ROLLBACK;
  12. END;

猜你在找的Oracle相关文章