源码-Oracle数据库管理-第十三章-子程序和包-Part 4(定义PL/SQL包)
来源:互联网 发布:英雄无敌 mac 10.13 编辑:程序博客网 时间:2024/05/29 17:22
业精于勤荒于嬉,行成于思毁于随!切记切记!
--代码13.12 包规范定义示例--定义包规范,包规范将被用于应用程序的接口部分,供外部调用CREATE OR REPLACE PACKAGE emp_pkg AS --定义集合类型 TYPE emp_tab IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER; --在包规范中定义一个记录类型 TYPE emprectyp IS RECORD( emp_no NUMBER, sal NUMBER ); --定义一个游标声明 CURSOR desc_salary RETURN emprectyp; --定义雇佣员工的过程 PROCEDURE hire_employee(p_empno NUMBER,p_ename VARCHAR2,p_job VARCHAR2,p_mgr NUMBER,p_sal NUMBER, p_comm NUMBER,p_deptno NUMBER); --定义解雇员工的过程 PROCEDURE fire_employee(p_emp_id NUMBER );END emp_pkg;--代码13.13 包体定义示例--定义包体CREATE OR REPLACE PACKAGE BODY emp_pkgAS --定义游标声明的游标体 CURSOR desc_salary RETURN emprectyp IS SELECT empno, sal FROM emp ORDER BY sal DESC; --定义雇佣员工的具体实现 PROCEDURE hire_employee(p_empno NUMBER,p_ename VARCHAR2, p_job VARCHAR2,p_mgr NUMBER,p_sal NUMBER, p_comm NUMBER,p_deptno NUMBER) IS BEGIN --向emp表中插入一条员工信息 INSERT INTO emp VALUES(p_empno,p_ename,p_job,p_mgr,SYSDATE,p_sal,p_comm,p_deptno); END; --定义解雇员工的具体实现 PROCEDURE fire_employee(p_emp_id NUMBER ) IS BEGIN --从emp表中删除员工信息 DELETE FROM emp WHERE empno=p_emp_id; END; END emp_pkg;--代码13.14 引用包中的游标DECLARE v_desc_sal_row emp_pkg.emprectyp; --定义游标返回类型变量BEGIN OPEN emp_pkg.desc_salary; --打开在包中定义的游标 LOOP FETCH emp_pkg.desc_salary INTO v_desc_sal_row;--提取游标数据 --输出员工信息 DBMS_OUTPUT.put_line('员工工号:'||v_desc_sal_row.emp_no ||' 员工工资:'||v_desc_sal_row.sal); EXIT WHEN emp_pkg.desc_salary%NOTFOUND; --提取完成退出游标 END LOOP; CLOSE emp_pkg.desc_salary; --关闭游标END;--13.3.2 定义包规范--代码13.15 定义人事信息管理包规范CREATE OR REPLACE PACKAGE emp_mgmt_pkg AS --添加新员工,返回新增员工的工号 FUNCTION hire(p_ename VARCHAR2, p_job VARCHAR2, p_mgr NUMBER, p_sal NUMBER, p_comm NUMBER, p_deptno NUMBER) RETURN NUMBER; --创建新部门,返回新增部门的部门编号 FUNCTION create_dept(p_deptno NUMBER, p_loc VARCHAR2) RETURN NUMBER; --移除一个员工 PROCEDURE remove_emp(p_empno NUMBER); --移除一个部门 PROCEDURE remove_dept(p_deptno NUMBER); --增加员工工资 PROCEDURE increase_sal(p_empno NUMBER, p_sal_incr NUMBER); --增加员工的提成 PROCEDURE increase_comm(p_empno NUMBER, p_comm_incr NUMBER); no_comm EXCEPTION; --没有提成数量的异常 no_sal EXCEPTION; --没有工资数量的异常END emp_mgmt_pkg;/DECLARE v_comm NUMBER:=&comm; --定义一个替换变量,要求用户输入一个值BEGIN IF v_comm<=0 THEN --如果输入的值小于或等于0 RAISE emp_mgmt_pkg.no_comm; --抛出在包中定义的异常 END IF;EXCEPTION WHEN emp_mgmt_pkg.no_comm THEN --在异常处理部分捕捉并处理该异常 DBMS_OUTPUT.put_line('没有指定员工提成!');END;--13.3.3 定义包体--代码13.16 实现人事信息管理包体CREATE OR REPLACE PACKAGE BODY emp_mgmt_pkg AS tot_emps NUMBER; --总员工数量 tot_depts NUMBER; --总的部门数量 --添加新员工,返回新增员工的工号 FUNCTION hire(p_ename VARCHAR2, p_job VARCHAR2, p_mgr NUMBER, p_sal NUMBER, p_comm NUMBER, p_deptno NUMBER) RETURN NUMBER AS v_empno NUMBER; BEGIN v_empno:=8350; INSERT INTO emp VALUES(v_empno,p_ename,p_job,p_mgr,SYSDATE,p_sal,p_comm,p_deptno); tot_emps := tot_emps + 1; RETURN v_empno; END hire; --创建新部门,返回新增部门的部门编号 FUNCTION create_dept(p_deptno NUMBER, p_loc VARCHAR2) RETURN NUMBER IS BEGIN INSERT INTO dept VALUES(p_deptno,'其他部门',p_loc); tot_depts := tot_depts + 1; RETURN p_deptno; END create_dept; --移除一个员工 PROCEDURE remove_emp(p_empno NUMBER) IS BEGIN DELETE FROM emp WHERE emp.empno = p_empno; tot_emps := tot_emps - 1; END remove_emp; --移除一个部门 PROCEDURE remove_dept(p_deptno NUMBER) IS BEGIN DELETE FROM dept WHERE dept.deptno = p_deptno; tot_depts := tot_depts - 1; SELECT COUNT(*) INTO tot_emps FROM emp; END remove_dept; --增加员工工资 PROCEDURE increase_sal(p_empno NUMBER, p_sal_incr NUMBER) IS curr_sal NUMBER; BEGIN SELECT sal INTO curr_sal FROM emp WHERE emp.empno= p_empno; IF curr_sal IS NULL THEN RAISE no_sal; ELSE UPDATE emp SET sal = sal + p_sal_incr WHERE empno = p_empno; END IF; END increase_sal; --增加员工的提成 PROCEDURE increase_comm(p_empno NUMBER, p_comm_incr NUMBER) IS curr_comm NUMBER; BEGIN SELECT comm INTO curr_comm FROM emp WHERE emp.empno = p_empno; IF curr_comm IS NULL THEN RAISE no_comm; ELSE UPDATE emp SET comm = comm + p_comm_incr WHERE emp.empno=p_empno; END IF; END increase_comm; BEGIN --包初始化部分 SELECT COUNT(*) INTO tot_emps FROM emp; SELECT COUNT(*) INTO tot_depts FROM dept; END emp_mgmt_pkg;--13.3.4 子程序重载--代码13.17 重载方法包规范示例CREATE OR REPLACE PACKAGE emp_mgmt_pkg_overloading AS --重载函数,添加新员工,返回新增员工的工号 FUNCTION hire(p_ename VARCHAR2, p_job VARCHAR2, p_mgr NUMBER, p_sal NUMBER, p_comm NUMBER, p_deptno NUMBER) RETURN NUMBER; --重载函数,添加新员工,返回新增员工的工号 FUNCTION hire(p_empno NUMBER, p_job VARCHAR2, p_deptno NUMBER) RETURN NUMBER; --重载函数,创建新部门,返回新增部门的部门编号 FUNCTION create_dept(p_deptno NUMBER, p_loc VARCHAR2) RETURN NUMBER; --重载函数,创建新部门,返回新增部门的部门编号 FUNCTION create_dept(p_deptno NUMBER,p_dname VARCHAR2,p_loc VARCHAR2) RETURN NUMBER; END emp_mgmt_pkg_overloading;--非法的重载方法,只是名称和模式的不同不能进行重载 FUNCTION create_dept(p_deptno IN NUMBER, p_loc IN VARCHAR2) RETURN NUMBER; FUNCTION create_dept(deptno IN NUMBER, loc IN OUT VARCHAR2) RETURN NUMBER; --非法的重载方法,函数的返回类型不同的不能进行重载 FUNCTION create_dept(p_deptno IN NUMBER, p_loc IN VARCHAR2) RETURN NUMBER; FUNCTION create_dept(p_deptno IN NUMBER, p_loc IN VARCHAR2) RETURN VARCHAR2; --非法的重载方法,不能对相同类型系统的参数进行重载 FUNCTION create_dept(p_deptno IN NUMBER, p_loc IN VARCHAR2) RETURN NUMBER; FUNCTION create_dept(p_deptno IN NUMBER, p_loc IN CHAR) RETURN VARCHAR2; --13.3.5 调用包组件--代码13.18 重载方法包体示例CREATE OR REPLACE PACKAGE BODY emp_mgmt_pkg_overloading AS --重载函数,添加新员工,返回新增员工的工号 FUNCTION hire(p_ename VARCHAR2, p_job VARCHAR2, p_mgr NUMBER, p_sal NUMBER, p_comm NUMBER, p_deptno NUMBER) RETURN NUMBER AS v_empno NUMBER; BEGIN v_empno:=8350; INSERT INTO emp VALUES(v_empno,p_ename,p_job,p_mgr,SYSDATE,p_sal,p_comm,p_deptno); RETURN v_empno; END; --重载函数,添加新员工,返回新增员工的工号 FUNCTION hire(p_empno NUMBER, p_job VARCHAR2, p_deptno NUMBER) RETURN NUMBER AS BEGIN INSERT INTO emp(empno,job,deptno) VALUES(p_empno,p_job,p_deptno); RETURN p_empno; END; --重载函数,创建新部门,返回新增部门的部门编号 FUNCTION create_dept(p_deptno NUMBER, p_loc VARCHAR2) RETURN NUMBER AS BEGIN INSERT INTO dept VALUES(p_deptno,'其他部门',p_loc); RETURN p_deptno; END; --重载函数,创建新部门,返回新增部门的部门编号 FUNCTION create_dept(p_deptno NUMBER,p_dname VARCHAR2,p_loc VARCHAR2) RETURN NUMBER AS BEGIN INSERT INTO dept VALUES(p_deptno,p_dname,p_loc); RETURN p_deptno; END; END emp_mgmt_pkg_overloading;select * from emp where ename='李三';BEGIN --重载方法使用示例,增加薪员工 emp_mgmt_pkg_overloading.hire('李三','分析员',NULL,3000,500,20); emp_mgmt_pkg_overloading.hire(8351,'销售员',20); --重载方法使用示例,创建新部门 emp_mgmt_pkg_overloading.create_dept(90,'南宁'); emp_mgmt_pkg_overloading.create_dept(91,'行政部','天津'); END;--13.3.5 调用包组件--代码13.19 有状态的包创建示例 --创建有状态的包规范,获取员工信息CREATE OR REPLACE PACKAGE stateful_emp_pkg AS --保存员工名称的索引表变量 TYPE t_emptable IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER; --获取最大行数 v_MaxRows NUMBER := 5; --读取员工名称到索引表中 PROCEDURE ReadEmp(p_emptable OUT t_emptable, p_NumRows OUT NUMBER);END stateful_emp_pkg;--创建有状态的包体,获取员工信息CREATE OR REPLACE PACKAGE BODY stateful_emp_pkg AS --定义包体游标,用来从emp表中查询员工数据 CURSOR c_empname IS SELECT ename FROM emp WHERE deptno = 20 ORDER BY empno; --实现包规范中的子程序,获取员工名称到索引表中 PROCEDURE ReadEmp(p_emptable OUT t_emptable, p_NumRows OUT NUMBER) AS v_Done BOOLEAN := FALSE; --是否游标财用完成 v_NumRows NUMBER := 1; --起始下标值 BEGIN DBMS_OUTPUT.put_line('正在打开游标'); IF NOT c_empname%ISOPEN THEN --判断游标是否打开,未打开则调用OPEN语句 OPEN c_empname; DBMS_OUTPUT.put_line('已经打开游标'); END IF; WHILE NOT v_Done LOOP --判断游标是否提取结束,如果还有数据则继续提取 FETCH c_empname INTO p_emptable(v_NumRows); --将游标数据保存到索引表中 IF c_empname%NOTFOUND THEN --如果游标提取完成 CLOSE c_empname; v_Done := TRUE; --关闭游标,并设置布尔变量 ELSE v_NumRows := v_NumRows + 1; --下标值加1 IF v_NumRows > v_MaxRows THEN --只提取v_MaxRows变量指定的行数 v_Done := TRUE; END IF; END IF; END LOOP; p_NumRows := v_NumRows - 1; --返回已经提取的行数 END ReadEmp;END stateful_emp_pkg;--代码13.20 状态包调用示例--匿名块的调用代码DECLARE v_emp_tbl stateful_emp_pkg.t_emptable; --定义索引表变量 v_numrows NUMBER ; --获取已提取的行数 v_ename emp.ename%TYPE; --定义一个嵌套子程序,用来输出信息 PROCEDURE read_emp AS BEGIN stateful_emp_pkg.ReadEmp(v_emp_tbl, v_numrows); --调用包中的方法读取emp表中的数据 DBMS_OUTPUT.PUT_LINE(' 已经提取了 ' || v_numrows || ' 行:'); FOR v_Count IN 1 .. v_NumRows LOOP --输出索引表中的员工名称 DBMS_OUTPUT.PUT_LINE(v_emp_tbl(v_Count)); END LOOP; END; BEGIN --显示当前的记录行数 DBMS_OUTPUT.put_line('当前v_MaxRows的值为:'||stateful_emp_pkg.v_MaxRows); read_emp; --调用嵌套的子程序调用包组件 stateful_emp_pkg.v_MaxRows:=3; --重新设置最大行数 DBMS_OUTPUT.put_line('当前v_MaxRows的值为:'||stateful_emp_pkg.v_MaxRows); read_emp; END;--代码13.21 可串行化复用包定义示例--创建有状态的包规范,获取员工信息CREATE OR REPLACE PACKAGE stateful_emp_pkg AS PRAGMA SERIALLY_REUSABLE; --保存员工名称的索引表变量 TYPE t_emptable IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER; --获取最大行数 v_MaxRows NUMBER := 5; --读取员工名称到索引表中 PROCEDURE ReadEmp(p_emptable OUT t_emptable, p_NumRows OUT NUMBER);END stateful_emp_pkg;--创建有状态的包体,获取员工信息CREATE OR REPLACE PACKAGE BODY stateful_emp_pkg AS PRAGMA SERIALLY_REUSABLE; --定义包体游标,用来从emp表中查询员工数据 CURSOR c_empname IS SELECT ename FROM emp WHERE deptno = 20 ORDER BY empno; --实现包规范中的子程序,获取员工名称到索引表中 PROCEDURE ReadEmp(p_emptable OUT t_emptable, p_NumRows OUT NUMBER) AS v_Done BOOLEAN := FALSE; --是否游标财用完成 v_NumRows NUMBER := 1; --起始下标值 BEGIN DBMS_OUTPUT.put_line('正在打开游标'); IF NOT c_empname%ISOPEN THEN --判断游标是否打开,未打开则调用OPEN语句 OPEN c_empname; DBMS_OUTPUT.put_line('已经打开游标'); END IF; WHILE NOT v_Done LOOP --判断游标是否提取结束,如果还有数据则继续提取 FETCH c_empname INTO p_emptable(v_NumRows); --将游标数据保存到索引表中 IF c_empname%NOTFOUND THEN --如果游标提取完成 CLOSE c_empname; v_Done := TRUE; --关闭游标,并设置布尔变量 ELSE v_NumRows := v_NumRows + 1; --下标值加1 IF v_NumRows > v_MaxRows THEN --只提取v_MaxRows变量指定的行数 v_Done := TRUE; END IF; END IF; END LOOP; p_NumRows := v_NumRows - 1; --返回已经提取的行数 END ReadEmp;END stateful_emp_pkg;--13.3.6 重新编译包--编译包规范scott_Ding@ORCL> ALTER PACKAGE stateful_emp_pkg COMPILE SPECIFICATION;Package altered.--编译包体scott_Ding@ORCL> ALTER PACKAGE stateful_emp_pkg COMPILE BODY; Package body altered.--同时编译包规范和包体scott_Ding@ORCL> ALTER PACKAGE stateful_emp_pkg COMPILE PACKAGE;Package altered.--13.3.7 查看包的源代码select object_name, object_type, created, last_ddl_time from user_objects where object_type in ('PACKAGE','PACKAGE BODY');SELECT line, text FROM user_source WHERE name ='EMP_PKG' AND type='PACKAGE';
0 0
- 源码-Oracle数据库管理-第十三章-子程序和包-Part 4(定义PL/SQL包)
- 源码-Oracle数据库管理-第十三章-子程序和包-Part 1(定义子程序)
- 源码-Oracle数据库管理-第十三章-子程序和包-Part 2(定义子程序)
- 源码-Oracle数据库管理-第十三章-子程序和包-Part 3(子程序参数)
- Oracle数据库编程:开发PL/SQL子程序和包
- 源码-Oracle数据库管理-第十二章-使用PL/SQL创建Oracle程序-Part 4(PL/SQL语言概览)
- 源码-PL/SQL从入门到精通-第十三章-子程序-Part 1
- 源码-PL/SQL从入门到精通-第十三章-子程序-Part 2
- 源码-Oracle数据库管理-第十二章-使用PL/SQL创建Oracle程序-Part 1(PL/SQL基础)
- 源码-Oracle数据库管理-第十二章-使用PL/SQL创建Oracle程序-Part 2(PL/SQL语言概览)
- 源码-Oracle数据库管理-第十二章-使用PL/SQL创建Oracle程序-Part 3(PL/SQL语言概览)
- 源码-Oracle数据库管理-第十二章-使用PL/SQL创建Oracle程序-Part 5(PL/SQL语言概览)
- 源码-Oracle数据库管理-第十四章-记录与集合-Part 1(使用PL/SQL记录)
- 源码-Oracle数据库管理-第十四章-记录与集合-Part 2(使用PL/SQL记录)
- 源码-Oracle数据库管理-第九章-SQL查询-Part 4(集合运算和子查询)
- oracle数据库PL/SQL之包
- Oracle数据库之PL/SQL包
- Oracle学习交流(4) -----开发子程序和包
- 寄存器位写操作
- 为什么网页设计要使用栅格化
- 数据库权限设计
- 自定义Django Command命令
- HDU 5093Battle ships
- 源码-Oracle数据库管理-第十三章-子程序和包-Part 4(定义PL/SQL包)
- Zili's Backlog
- qq聊天记录词频查询 python实现
- 关于Tomcat启动报错:Failed to initialize end point associated with ProtocolHandler ["http-apr-8080"]
- Git 的 .gitignore 配置
- 十六进制转十进制
- 从头开始学java<五>
- Unix环境高级编程--多线程(一)
- Intent单例