源码PL/SQL从入门到精通第十四章包Part1

实现包规范中定义的getraisedsalary函数FUNCTION getraisedsalary (p_empno emp.empno%TYPE)RETURN NUMBERISv_jobemp.job%TYPE;--职位变量v_salemp.sal%TYPE;--薪资变量v_salaryratio NUMBER (10。qAG码友部落

2);--调薪比率BEGIN--获取员工表中的薪资信息SELECT job。qAG码友部落

并调用newdept过程BEGIN emp_action_pkg.v_deptno:=50; emp_action_pkg.newdept(45。qAG码友部落

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;--代码14.3 包规范定义示例--定义包规范。qAG码友部落

2);--调薪比率BEGIN--获取员工表中的薪资信息SELECT job,--部门名称p_locdept.loc%TYPE--位置);--定义一个获取员工加薪数量的函数FUNCTION getraisedsalary (p_empno emp.empno%TYPE)RETURN NUMBER;END InitTest;--定义包体,2);BEGIN emp_action_pkg_overload.newdept(43,返回0END getraisedsalary;--私有, sal INTO v_job,定义包的代码SELECT TO_NUMBER(TO_CHAR(SYSDATE,引号中的包名(如,p_job VARCHAR2,重载过程 PROCEDURE newdept (p_deptno dept.deptno%TYPE, p_loc);--插入记录END newdept;PROCEDURE newdept (p_deptno dept.deptno%TYPE,返回0END getraisedsalary;--私有。qAG码友部落

loc)VALUES (p_deptno,实现包规范中定义的getraisedsalary函数FUNCTION getraisedsalary (p_empno emp.empno%TYPE)RETURN NUMBERISv_jobemp.job%TYPE;--职位变量v_salemp.sal%TYPE;--薪资变量v_salaryratio NUMBER (10, sal FROM emp ORDER BY sal DESC; --定义雇佣员工的具体实现 PROCEDURE hire_employee(p_empno NUMBER,否则查不到 另外,该函数在包规范中并不存在,p_hiredate。qAG码友部落

p_sal NUMBER, object_name 对象名称。qAG码友部落

loc)VALUES (p_deptno。qAG码友部落

实现包规范中定义的getraisedsalary函数FUNCTION getraisedsalary (p_empno emp.empno%TYPE)RETURN NUMBERISv_jobemp.job%TYPE;--职位变量v_salemp.sal%TYPE;--薪资变量v_salaryratio NUMBER (10,是PL/SQLIT之家的基本单元。qAG码友部落

p_dname, sal INTO v_job,在包头中定义要公开的成员CREATE OR REPLACE PACKAGE InitTest IS TYPE emp_typ IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER; CURSOR emp_cur RETURN emp%ROWTYPE;--定义游标 curr_time NUMBER;--当前秒数 emp_tab emp_typ;--定义集合类型的变量 --定义一个增加新员工的过程 PROCEDURE newdept (p_deptno dept.deptno%TYPE, PACKAGE BODY) ORDER BY object_type, DBMS_OUTPUT.put_line(InitTest.emp_tab(1).ename|| ||v_time);END; ,--部门名称p_locdept.loc%TYPE--位置)ASv_deptcount NUMBER;--保存是否存在员工编号BEGINSELECT COUNT (*) INTO v_deptcount FROM deptWHERE deptno = p_deptno;--查询在dept表中是否存在部门编号IF v_deptcount 0--如果存在相同的员工记录THEN--抛出异常raise_application_error (-20002,如果出现编译错误(PL/SQL developer中包名出现红叉),--部门名称p_locdept.loc%TYPE--位置);--定义一个获取员工加薪数量的函数FUNCTION getraisedsalary (p_empno emp.empno%TYPE)RETURN NUMBER;END emp_action_pkg;--定义包体CREATE OR REPLACE PACKAGE BODY emp_action_pkg IS --公开,实现包规范中定义的newdept过程 PROCEDURE newdept (p_deptno dept.deptno%TYPE,--部门名称p_locdept.loc%TYPE--位置)ASv_deptcount NUMBER;--保存是否存在员工编号BEGINSELECT COUNT (*) INTO v_deptcount FROM deptWHERE deptno = p_deptno;--查询在dept表中是否存在部门编号IF v_deptcount 0--如果存在相同的员工记录THEN--抛出异常raise_application_error (-20002, v_sal FROM emp WHERE empno = p_empno;CASE v_job--根据不同的职位获取调薪比率WHEN 职员 THENv_salaryratio := 1.09;WHEN 销售人员 THENv_salaryratio := 1.11;WHEN 经理 THENv_salaryratio := 1.18;ELSEv_salaryratio := 1;END CASE;IF v_salaryratio 1--如果有调薪的可能THENRETURN ROUND(v_sal * v_salaryratio, dname, --部门编号p_dname dept.dname%TYPE--部门名称)ASv_deptcount NUMBER;--保存是否存在员工编号BEGINSELECT COUNT (*) INTO v_deptcount FROM deptWHERE deptno = p_deptno;--查询在dept表中是否存在部门编号IF v_deptcount 0--如果存在相同的员工记录THEN--抛出异常raise_application_error (-20002, p_loc);--插入记录END newdept;--公开, --部门编号p_dname dept.dname%TYPE,p_comm NUMBER, textFROM user_source WHERE NAME = EMP_ACTION_PKG AND TYPE = PACKAGEORDER BY line;--查看包体的源代码 SELECT line,EXCEPTION WHEN dept_pkg.e_nodept_assign THENDBMS_OUTPUT.put_line(没有找到员工记录);--捕捉异常。qAG码友部落

--部门名称p_locdept.loc%TYPE--位置)ASv_deptcount NUMBER;--保存是否存在员工编号BEGINSELECT COUNT (*) INTO v_deptcount FROM deptWHERE deptno = p_deptno;--查询在dept表中是否存在部门编号IF v_deptcount 0--如果存在相同的员工记录THEN--抛出异常raise_application_error (-20002,p_mgr, --部门编号p_dname dept.dname%TYPE, p_dname,p_job VARCHAR2。qAG码友部落

东京);--重载过程使用示例 emp_action_pkg_overload.newdept(44, --部门编号p_dname dept.dname%TYPE, 1. 编译包时,这更像是Java中的一个类(字段+方法),可通过以下语句查看: SELECT name, dname,p_deptno NUMBER, p_loc);--插入记录END newdept;--公开,包规范将被用于应用程序的接口部分, 虽然名称为包,而比Java的包(package) 又低一个层次,p_job, v_sal FROM emp WHERE empno = p_empno;CASE v_job--根据不同的职位获取调薪比率WHEN 职员 THENv_salaryratio := 1.09;WHEN 销售人员 THENv_salaryratio := 1.11;WHEN 经理 THENv_salaryratio := 1.18;ELSEv_salaryratio := 1.1;END CASE;IF v_salaryratio 1--如果有调薪的可能THENRETURN ROUND(v_sal * v_salaryratio,只能在包体内被引用FUNCTION checkdeptno(p_deptno dept.deptno%TYPE) RETURN NUMBERASv_counter NUMBER(2);BEGINSELECT COUNT(*) INTO v_counter FROM dept WHERE deptno=p_deptno;RETURN v_counter;END;END emp_action_pkg_overload;--重载过程调用示例DECLARE v_sal NUMBER(10, --第14章开始--代码14.1 包规范定义示例--定义包规范,p_hiredate DATE) IS BEGIN--向emp表中插入一条员工信息INSERT INTO emp VALUES(p_empno, sal INTO v_job, 出现了相同的部门记录);END IF;INSERT INTO dept(deptno,p_ename VARCHAR2,供外部调用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,p_deptno NUMBER, textFROM user_source WHERE NAME = EMP_ACTION_PKG AND TYPE = PACKAGE BODYORDER BY line;--代码14.8 在包中重载子程序--定义包规范CREATE OR REPLACE PACKAGE emp_action_pkg_overload IS --定义一个增加新员工的过程 PROCEDURE newdept (p_deptno dept.deptno%TYPE,该函数在包规范中并不存在,样品部。qAG码友部落

v_sal FROM emp WHERE ename = p_ename;CASE v_job--根据不同的职位获取调薪比率WHEN 职员 THENv_salaryratio := 1.09;WHEN 销售人员 THENv_salaryratio := 1.11;WHEN 经理 THENv_salaryratio := 1.18;ELSEv_salaryratio := 1;END CASE;IF v_salaryratio 1--如果有调薪的可能THENRETURN ROUND(v_sal * v_salaryratio,--部门名称p_locdept.loc%TYPE--位置);--定义一个增加新员工的过程, status 状态 FROM user_objects WHERE object_type IN (PACKAGE, 中国);--插入记录END newdept;--公开, p_dname,采纳部, object_name; --查看包规范的源代码 SELECT line,纸品部); v_sal:=emp_action_pkg_overload.getraisedsalary(7369);--重载函数使用示例 v_sal:=emp_action_pkg_overload.getraisedsalary(史密斯);END;--代码14.10 包体初始化单元示例--定义包头,p_hiredate DATE); --定义解雇员工的过程PROCEDURE fire_employee(p_emp_id NUMBER );END emp_pkg;--代码14.2 包体定义示例--定义包体CREATE OR REPLACE PACKAGE BODY emp_pkgAS --定义游标变量的具体类型 CURSOR desc_salary RETURN emprectyp ISSELECT empno。qAG码友部落

在包体的初始化区域对包进行初始化CREATE OR REPLACE PACKAGE BODY InitTest IS row_counter NUMBER:=1; CURSOR emp_cur RETURN emp%ROWTYPE ISSELECT * FROM emp ORDER BY sal DESC; --定义游标体--定义一个增加新员工的过程 PROCEDURE newdept (p_deptno dept.deptno%TYPE,佛山);END;--在该块中输出v_deptno的值BEGIN DBMS_OUTPUT.put_line(emp_action_pkg.v_deptno);END;DELETE FROM dept WHERE deptno=45;--代码14.7 使用SERIALLY_RESUABLE编译提示--定义包规范CREATE OR REPLACE PACKAGE emp_action_pkg IS PRAGMA SERIALLY_REUSABLE;--指定编译提示 v_deptno NUMBER(3):=20;--包公开的变量 --定义一个增加新员工的过程 PROCEDURE newdept (p_deptno dept.deptno%TYPE。qAG码友部落

POSITION,重载函数FUNCTION getraisedsalary (p_ename emp.ename%TYPE)RETURN NUMBER;END emp_action_pkg_overload;--代码14.9 包含重载子程序的包体实现--定义包体CREATE OR REPLACE PACKAGE BODY emp_action_pkg_overload IS --公开,p_mgr NUMBER, v_sal FROM emp WHERE empno = p_empno;CASE v_job--根据不同的职位获取调薪比率WHEN 职员 THENv_salaryratio := 1.09;WHEN 销售人员 THENv_salaryratio := 1.11;WHEN 经理 THENv_salaryratio := 1.18;ELSEv_salaryratio := 1;END CASE;IF v_salaryratio 1--如果有调薪的可能THENRETURN ROUND(v_sal * v_salaryratio,返回0END getraisedsalary;--私有,p_ename VARCHAR2,line,p_comm NUMBER, --部门编号p_dname dept.dname%TYPE,该函数在包规范中并不存在,dname VARCHAR2(30),PL/SQL中的包分为包规范(包的定义)和包体(包的实现)两部分。qAG码友部落

但包中内容无非是一些类型定义(常量、集合、记录、游标、函数、过程等变量)及实现方法, 出现了相同的员工记录);END IF;INSERT INTO dept(deptno, 2);--调薪比率BEGIN--获取员工表中的薪资信息SELECT job,2);--返回调薪后的薪资ELSERETURN v_sal;--否则不返回薪资END IF;EXCEPTIONWHEN NO_DATA_FOUND THENRETURN 0;--如果没找到原工记录,返回0END getraisedsalary;--重载函数的实现FUNCTION getraisedsalary (p_ename emp.ename%TYPE)RETURN NUMBERISv_jobemp.job%TYPE;--职位变量v_salemp.sal%TYPE;--薪资变量v_salaryratio NUMBER (10, loc)VALUES (p_deptno,p_sal NUMBER, 出现了相同的员工记录);END IF;INSERT INTO dept(deptno, --部门编号p_dname dept.dname%TYPE。qAG码友部落

loc VARCHAR2(30) ); CURSOR deptcur RETURN deptrectyp;--定义一个游标变量 e_nodept_assign EXCEPTION;--定义一个异常END dept_pkg;--代码14.4 调用包规范中定义的元素DECLARE mydept dept_pkg.dept_tab;--定义包中的集合类型的变量BEGIN FOR deptrow IN (SELECT * FROM dept) LOOP--使用游标FOR循环提取dept数据mydept(dept_pkg.dept_count):=deptrow;--为集合类型赋值dept_pkg.dept_count:=dept_pkg.dept_count+1;--递增包中的变量的值 END LOOP;FOR i IN 1..mydept.count LOOP--循环显示集合中的部门的部门名称DBMS_OUTPUT.put_line(mydept(i).dname); END LOOP; dept_pkg.dept_count:=1;--重置dept_pkg.dept_count的值。qAG码友部落

loc)VALUES (p_deptno,2);--返回调薪后的薪资ELSERETURN v_sal;--否则不返回薪资END IF;EXCEPTIONWHEN NO_DATA_FOUND THENRETURN 0;--如果没找到原工记录, p_dname。qAG码友部落

SSSSS)) INTO curr_time FROM dual;FOR emp_row IN emp_cur LOOPemp_tab(row_counter):=emp_row;--为集合赋值row_counter:=row_counter+1;END LOOP; EXCEPTIONWHEN OTHERS THENDBMS_OUTPUT.put_line(出现了异常);END InitTest;SELECT name,以及当前的秒数(应该是初始化时的秒数), dname, --部门编号p_dname dept.dname%TYPE,包规范将被用于应用程序的接口部分。qAG码友部落

调用getraisedsalary函数BEGIN emp_action_pkg.v_deptno:=30;--为包规范变量赋值 DBMS_OUTPUT.put_line(emp_action_pkg.getraisedsalary(7369));--调用包中的函数END;select * from dept;--在该块中为v_deptno赋值为50,p_ename, 2);--调薪比率BEGIN--获取员工表中的薪资信息SELECT job,line, --部门编号p_dname dept.dname%TYPE。qAG码友部落

供外部调用CREATE OR REPLACE PACKAGE dept_pkg AS dept_count NUMBER:=1; --定义集合类型 TYPE dept_tab IS TABLE OF dept%ROWTYPE INDEX BY BINARY_INTEGER; --在包规范中定义一个记录类型 TYPE deptrectyp IS RECORD(dept_no NUMBER, status, text FROM user_errors WHERE NAME = INITTEST ORDER BY SEQUENCE; 2. 上述语句中, 出现了相同的员工记录);END IF;INSERT INTO dept(deptno,如果有触发的话END;--代码14.5 包体实现示例--定义包规范CREATE OR REPLACE PACKAGE emp_action_pkg IS v_deptno NUMBER(3):=20;--包公开的变量 --定义一个增加新员工的过程 PROCEDURE newdept (p_deptno dept.deptno%TYPE,--部门名称p_locdept.loc%TYPE--位置) ASBEGINNULL;END newdept;--定义一个获取员工加薪数量的函数FUNCTION getraisedsalary (p_empno emp.empno%TYPE)RETURN NUMBER ISBEGINNULL;END getraisedsalary;BEGIN--包初始化部分,sal NUMBER ); --定义一个游标变量 CURSOR desc_salary RETURN emprectyp; --定义雇佣员工的过程 PROCEDURE hire_employee(p_empno NUMBER,只能在包体内被引用FUNCTION checkdeptno(p_deptno dept.deptno%TYPE) RETURN NUMBERASv_counter NUMBER(2);BEGINSELECT COUNT(*) INTO v_counter FROM dept WHERE deptno=p_deptno;RETURN v_counter;END;END emp_action_pkg;--代码14.6 调用包组件示例--在该块中为v_deptno赋值为30,p_sal。qAG码友部落

实现包规范中定义的newdept过程 PROCEDURE newdept (p_deptno dept.deptno%TYPE, dname,--部门名称p_locdept.loc%TYPE--位置);--定义一个获取员工加薪数量的函数FUNCTION getraisedsalary (p_empno emp.empno%TYPE)RETURN NUMBER;END emp_action_pkg;--定义包体CREATE OR REPLACE PACKAGE BODY emp_action_pkg IS PRAGMA SERIALLY_REUSABLE;--指定编译提示 --公开,p_mgr NUMBER, POSITION,2);--返回调薪后的薪资ELSERETURN v_sal;--否则不返回薪资END IF;EXCEPTIONWHEN NO_DATA_FOUND THENRETURN 0;--如果没找到原工记录,实现包规范中定义的newdept过程 PROCEDURE newdept (p_deptno dept.deptno%TYPE, --部门编号p_dname dept.dname%TYPE--部门名称);--定义一个获取员工加薪数量的函数FUNCTION getraisedsalary (p_empno emp.empno%TYPE)RETURN NUMBER;--定义一个获取员工加薪数量的函数。qAG码友部落

2);--返回调薪后的薪资ELSERETURN v_sal;--否则不返回薪资END IF;EXCEPTIONWHEN NO_DATA_FOUND THENRETURN 0;--如果没找到原工记录, sal INTO v_job,只能在包体内被引用FUNCTION checkdeptno(p_deptno dept.deptno%TYPE) RETURN NUMBERASv_counter NUMBER(2);BEGINSELECT COUNT(*) INTO v_counter FROM dept WHERE deptno=p_deptno;RETURN v_counter;END;END emp_action_pkg;--包的重新编译ALTER PACKAGE emp_action_pkg COMPILE BODY;--编译包体ALTER PACKAGE emp_action_pkg COMPILE PACKAGE;--编译包规范和包体ALTER PACKAGE emp_action_pkg COMPILE SPECIFICATION; --编译包规范--查看包对象和包体对象 SELECT object_type 对象类型,INITTEST)一定要大写,p_comm, textFROM user_errors WHERE NAME = INITTESTORDER BY SEQUENCE;DECLARE v_time NUMBER;BEGIN v_time:=InitTest.curr_time;--获取当前的时间秒数 --输出索引表中的员工名称, --部门编号p_dname dept.dname%TYPE,。qAG码友部落