您的位置:首页 > 数据库

源码-PL/SQL从入门到精通-第十七章-面向对象编程-Part 1

2016-07-26 17:13 330 查看
原来PL/SQL也支持面向对象编程,有了Java基础,这章不难理解。

有个问题:对象定义真不支持布尔类型? 我的Java程序中布尔型可是很常用的啊。不过肯定有其他的替代解决方案吧


--第17章开始
--代码17.1 定义employee_obj对象类型规范
--定义对象类型规范employee_obj
CREATE OR REPLACE TYPE employee_obj AS OBJECT (
--定义对象类型属性
empno NUMBER(4),
ename VARCHAR2(20),
job VARCHAR2(20),
sal NUMBER(10,2),
comm NUMBER(10,2),
deptno NUMBER(4),
--定义对象类型方法
MEMBER PROCEDURE Change_sal(p_empno NUMBER,p_sal NUMBER),
MEMBER PROCEDURE Change_comm(p_empno NUMBER,p_comm NUMBER),
MEMBER PROCEDURE Change_deptno(p_empno NUMBER,p_deptno NUMBER),
MEMBER FUNCTION get_sal(p_empno NUMBER) RETURN NUMBER,
MEMBER FUNCTION get_comm(p_empno NUMBER) RETURN NUMBER,
MEMBER FUNCTION get_deptno(p_empno NUMBER) RETURN INTEGER
) NOT FINAL; --指定该类可以被继承,如果指定FINAL,表示该类无法被继承

--代码 17.2 定义对象类型体
CREATE OR REPLACE TYPE BODY employee_obj
AS
MEMBER PROCEDURE change_sal (p_empno NUMBER, p_sal NUMBER)
IS --定义对象成员方法,更改员工薪资
BEGIN
UPDATE emp
SET sal = p_sal
WHERE empno = p_empno;
END;
MEMBER PROCEDURE change_comm (p_empno NUMBER, p_comm NUMBER)
IS --定义对象成员方法,更改员工提成
BEGIN
UPDATE emp
SET comm = p_comm
WHERE empno = p_empno;
END;
MEMBER PROCEDURE change_deptno (p_empno NUMBER, p_deptno NUMBER)
IS --定义对象成员方法,更改员工部门
BEGIN
UPDATE emp
SET deptno = p_deptno
WHERE empno = p_empno;
END;
MEMBER FUNCTION get_sal (p_empno NUMBER)
RETURN NUMBER
IS --定义对象成员方法,获取员工薪资
v_sal NUMBER (10, 2);
BEGIN
SELECT sal
INTO v_sal
FROM emp
WHERE empno = p_empno;
RETURN v_sal;
END;
MEMBER FUNCTION get_comm (p_empno NUMBER)
RETURN NUMBER
IS --定义对象成员方法,获取员工提成
v_comm NUMBER (10, 2);
BEGIN
SELECT comm
INTO v_comm
FROM emp
WHERE empno = p_empno;
RETURN v_comm;
END;
MEMBER FUNCTION get_deptno (p_empno NUMBER)
RETURN INTEGER
IS --定义对象成员方法,获取员工部门
v_deptno INT;
BEGIN
SELECT deptno
INTO v_deptno
FROM emp
WHERE empno = p_empno;
RETURN v_deptno;
END;
END;

--代码17.3 定义对象的属性
--定义对象类型规范employee_obj
CREATE OR REPLACE TYPE employee_property AS OBJECT (
--定义对象类型属性
empno NUMBER(4),
ename VARCHAR2(20),
job VARCHAR2(20),
sal NUMBER(10,2),
comm NUMBER(10,2),
deptno NUMBER(4)
) NOT FINAL; --对象类型可以被继承

--代码17.4 实例化对象并设置或获取对象属性
DECLARE
v_emp employee_property; --定义对象类型
v_sal v_emp.sal%TYPE; --定义对象类型中与sal类型相同的薪资变量
BEGIN
--初始化对象类型,v_emp是一个对象的实例
v_emp := employee_property (7890, '赵五', '销售人员', 5000, 200, 20);
v_sal := v_emp.sal; --为变量赋对象实例的值
--获取对象类型的属性进行显示
DBMS_OUTPUT.put_line (v_emp.ename || ' 的薪资是:' || v_sal);
END;

--代码17.5 使用Member和Static成员方法(不好调试啊!->调试通过!)
--定义对象类型规范employee_salobj

CREATE OR REPLACE TYPE employee_method AS OBJECT (
--定义对象类型属性
empno NUMBER (4),
sal NUMBER (10, 2),
comm NUMBER (10, 2),
deptno NUMBER (4),
--定义对象类型方法
MEMBER PROCEDURE change_sal, --实例方法,可以访问对象本身的属性
MEMBER FUNCTION get_sal RETURN NUMBER,
--静态方法,不能访问对象本身的属性,只能访问静态数据
STATIC PROCEDURE change_deptno (p_empno NUMBER, p_deptno NUMBER),
STATIC FUNCTION get_sal (p_empno NUMBER) RETURN NUMBER
)
NOT FINAL; --指定该类可以被继承,如果指定FINAL,表示该类无法被继承
----------------------------------------------------------------------------------
--定义employee_method对象类型体
CREATE OR REPLACE TYPE BODY employee_method
AS
MEMBER PROCEDURE change_sal
IS
BEGIN
SELF.sal := SELF.sal * 1.12; --使用SELF关键字
END;
MEMBER FUNCTION get_sal
RETURN NUMBER
IS
BEGIN
RETURN sal; --返回员工薪资
END;
STATIC PROCEDURE change_deptno (p_empno NUMBER, p_deptno NUMBER)
IS --定义对象成员方法,更改员工部门
BEGIN
UPDATE emp
SET deptno = p_deptno
WHERE empno = p_empno;
END;
STATIC FUNCTION get_sal (p_empno NUMBER)
RETURN NUMBER
IS --定义对象成员方法,获取员工薪资
v_sal NUMBER (10, 2);
BEGIN
SELECT sal
INTO v_sal
FROM emp
WHERE empno = p_empno;
RETURN v_sal;
END;
END;

--代码17.6 Member和Static方法使用示例
DECLARE
v_emp employee_method; --定义employee_method对象类型的变量
BEGIN
v_emp:=employee_method(5093,5000,200,20); --实例化employee_method对象,现在v_emp是对象实例
v_emp.change_sal; --设用对象实例方法,即MEMBER方法
DBMS_OUTPUT.put_line('员工编号为:'||v_emp.empno||' 的薪资为:'||v_emp.get_sal);
--下面的代码调用STATIC方法更新emp表中员工编号为7369的部门编号为20.
employee_method.change_deptno(5093,20);
--下面的代码获取emp表中员工编号为7369的员工薪资。
DBMS_OUTPUT.put_line('员工编号为5093的薪资为:'||employee_method.get_sal(5093));
END;

drop trigger t_comm_sal;
select * from emp;

--代码17.7 访问对象类型的属性
--定义对象类型规范employee_salobj
CREATE OR REPLACE TYPE employee_salobj AS OBJECT (
--定义对象类型属性
empno NUMBER (4),
sal NUMBER (11, 2),
comm NUMBER (10, 2),
deptno NUMBER (4),
--定义对象类型方法
MEMBER PROCEDURE change_sal,
MEMBER PROCEDURE change_comm,
MEMBER PROCEDURE change_deptno,
MEMBER FUNCTION get_sal
RETURN NUMBER,
MEMBER FUNCTION get_comm
RETURN NUMBER,
MEMBER FUNCTION get_deptno
RETURN INTEGER
)
NOT FINAL; --指定该类可以被继承,如果指定FINAL,表示该类无法被继承
----------------------------------------------------------------------------------
--定义employee_salobj对象类型体
CREATE OR REPLACE TYPE BODY employee_salobj
AS
MEMBER PROCEDURE change_sal
IS
BEGIN
SELF.sal := SELF.sal * 1.12; --使用SELF关键字
END;
MEMBER PROCEDURE change_comm
IS
BEGIN
comm := comm * 1.12; --不使用SELF关键字
END;
MEMBER PROCEDURE change_deptno
IS
BEGIN
SELF.deptno := 20; --使用SELF关键字更改部门名称
END;
MEMBER FUNCTION get_sal
RETURN NUMBER
IS
BEGIN
RETURN sal; --返回员工薪资
END;
MEMBER FUNCTION get_comm
RETURN NUMBER
IS
BEGIN
RETURN SELF.comm; --返回员工提成
END;
MEMBER FUNCTION get_deptno
RETURN INTEGER
IS
BEGIN
RETURN SELF.deptno; --返回员工部门编号
END;
END;

--代码17.8 自定义构造函数
--定义对象类型规范
CREATE OR REPLACE TYPE salary_obj AS OBJECT (
percent NUMBER(10,4), --定义对象属性
sal NUMBER(10,2),
--自定义构造函数
CONSTRUCTOR FUNCTION salary_obj(p_sal NUMBER) RETURN SELF AS RESULT)
INSTANTIABLE --可实例化对象
FINAL; --不可以继承
/
--定义对象类型体
CREATE OR REPLACE TYPE BODY salary_obj
AS
--实现重载的构造函数
CONSTRUCTOR FUNCTION salary_obj (p_sal NUMBER)
RETURN SELF AS RESULT
AS
BEGIN
SELF.sal := p_sal; --设置属性值
SELF.PERCENT := 1.12; --为属性指定初值
RETURN;
END;
END;
/

DECLARE
v_salobj1 salary_obj;
v_salobj2 salary_obj; --定义对象类型
BEGIN
v_salobj1 := salary_obj (1.12, 3000); --使用默认构造函数
v_salobj2 := salary_obj (2000); --使用自定义构造函数
END;

--代码17.9 定义Map函数示例
--定义一个对象规范,该规范中包含MAP方法
CREATE OR REPLACE TYPE employee_map AS OBJECT (
--定义对象类型属性
empno NUMBER (4),
sal NUMBER (10, 2),
comm NUMBER (10, 2),
deptno NUMBER (4),
MAP MEMBER FUNCTION convert RETURN REAL --定义一个MAP方法
)
NOT FINAL;
--定义一个对象类型体,实现MAP函数
CREATE OR REPLACE TYPE BODY employee_map AS
MAP MEMBER FUNCTION convert RETURN REAL IS --定义一个MAP方法
BEGIN
RETURN sal+comm; --返回标量类型的值
END;
END;

--创建employee_map类型的对象表
CREATE TABLE emp_map_tab OF employee_map;
--向对象表中插入员工薪资信息对象。
INSERT INTO emp_map_tab VALUES(7123,3000,200,20);
INSERT INTO emp_map_tab VALUES(7124,2000,800,20);
INSERT INTO emp_map_tab VALUES(7125,5000,800,20);
INSERT INTO emp_map_tab VALUES(7129,3000,400,20);

SELECT VALUE(r) val,r.sal+r.comm FROM emp_map_tab r ORDER BY 1;

--代码17.10 定义Order函数示例
--定义一个对象规范,该规范中包含ORDER方法
CREATE OR REPLACE TYPE employee_order AS OBJECT (
--定义对象类型属性
empno NUMBER (4),
sal NUMBER (10, 2),
comm NUMBER (10, 2),
deptno NUMBER (4),
ORDER MEMBER FUNCTION match(r employee_order) RETURN INTEGER --定义一个ORDER方法
)
NOT FINAL;
--定义一个对象类型体,实现ORDER函数
CREATE OR REPLACE TYPE BODY employee_order AS
ORDER MEMBER FUNCTION match(r employee_order) RETURN INTEGER IS
BEGIN
IF ((SELF.sal+SELF.comm)<(r.sal+r.comm)) THEN
RETURN -1; --可为任何负数
ELSIF ((SELF.sal+SELF.comm)>(r.sal+r.comm)) THEN
RETURN 1; --可为任何正数
ELSE
RETURN 0; --如果相等则为0
END IF;
END match;
END;

DECLARE
emp1 employee_order:=employee_order(7112,3000,200,20); --定义员工1
emp2 employee_order:=employee_order(7113,3800,100,20); --定义员工2
BEGIN
--对员工1和2进行比较,获取返回结果
IF emp1>emp2 THEN
DBMS_OUTPUT.put_line('员工1的薪资加提成比员工2大!');
ELSIF emp1<emp2 THEN
DBMS_OUTPUT.put_line('员工1的薪资加提成比员工2小!');
ELSE
DBMS_OUTPUT.put_line('员工1的薪资加提成与员工2相等!');
END IF;
END;

--创建employee_order类型的对象表
CREATE TABLE emp_order_tab OF employee_order;
--向对象表中插入员工薪资信息对象。
INSERT INTO emp_order_tab VALUES(7123,3000,200,20);
INSERT INTO emp_order_tab VALUES(7124,2000,800,20);
INSERT INTO emp_order_tab VALUES(7125,5000,800,20);
INSERT INTO emp_order_tab VALUES(7129,3000,400,20);
SELECT VALUE(r) val,r.sal+r.comm FROM emp_order_tab r ORDER BY 1;

--方法中定义的

--代码17.11 使用对象类型
DECLARE
o_emp employee_order; --定义对象实例,初始状态下为NULL
BEGIN
o_emp := employee_order (7123, 3000, 200, 20); --使用构造函数声明对象
DBMS_OUTPUT.put_line ( '员工编号为:'
|| o_emp.empno
|| '的薪资和提成为:'
|| (o_emp.sal + o_emp.comm)
);
END;

--代码17.12 在子程序中使用对象类型
--使用对象类型作为过程的形式参数
CREATE OR REPLACE PROCEDURE changesalary(p_emp IN employee_order)
AS
BEGIN
IF p_emp IS NOT NULL THEN --如果对象类型已经被实例化
--更新emp表
UPDATE emp SET sal=p_emp.sal,comm=p_emp.comm WHERE empno=p_emp.empno;
END IF;
END changesalary;
--使用对象类型作为函数的传入传出参数
CREATE OR REPLACE FUNCTION getsalary(p_emp IN OUT employee_order) RETURN NUMBER
AS
BEGIN
IF p_emp IS NOT NULL THEN --如果对象类型没有被实例化
p_emp:=employee_order(7125,5000,800,20); --实例化对象类型
END IF;
RETURN p_emp.sal+p_emp.comm; --返回对象类型的薪资和提成汇总
END;

DECLARE
o_emp employee_order;
BEGIN
o_emp.empno:=7301; --错误:该对象实例还没有被初始化就进行了赋值
END;

--好的编程习惯:定义变量时进行初始化
DECLARE
o_emp employee_order :=
employee_order (NULL, NULL, NULL, NULL); --初始化对象类型
BEGIN
o_emp.empno := 7301; --为对象类型赋值
o_emp.sal := 5000;
o_emp.comm := 300;
o_emp.deptno := 20;
END;

--代码17.13 调用静态方法与示例方法示例
--employee_method对象类型的实例方法与静态方法列表
CREATE OR REPLACE TYPE employee_method AS OBJECT (
empno NUMBER (4),
sal NUMBER (11, 2),
comm NUMBER (10, 2),
deptno NUMBER (4),
--定义对象类型方法
MEMBER PROCEDURE change_sal, --实例方法,可以访问对象本身的属性
MEMBER FUNCTION get_sal RETURN NUMBER,
--静态方法,不能访问对象本身的属性,只能访问静态数据
STATIC PROCEDURE change_deptno (empno NUMBER, deptno NUMBER),
STATIC FUNCTION get_sal (empno NUMBER) RETURN NUMBER
)
NOT FINAL;
--演示调用employee_method的实例方法与静态方法 (调试未成功)
DECLARE
o_emp employee_method:=employee_method(5093,5000,800,20);
v_sal NUMBER(11,2);
BEGIN
v_sal:=o_emp.get_sal; --调用对象实例方法
DBMS_OUTPUT.put_line('对象实例级别的工资为:'||v_sal);
v_sal:=employee_method.get_sal(o_emp.empno); --调用静态方法
DBMS_OUTPUT.put_line('对象类型级别的工资为:'||v_sal);
END;

DROP TYPE APPS.ADDRESS_TYPE;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: