范例:定义类规范
CREATE OR REPLACE TYPE emp_object AS OBJECT ( -- 定义对象属性,与emp表对应 atri_empno NUMBER(4) , -- 雇员编号 atri_sal NUMBER(7,2) , -- 雇员工资 atri_deptno NUMBER(2) , -- 部门编号 -- 定义对象操作方法 -- 此过程的功能是根据部门编号按照一定的百分比增长部门雇员的工资 MEMBER PROCEDURE change_dept_sal_proc(p_deptno NUMBER, p_percent NUMBER) , -- 此函数的功能是取得指定雇员的工资(包括基本工资和佣金) MEMBER FUNCTION get_sal_fun(p_empno NUMBER) RETURN NUMBER ) NOT FINAL ; / |
范例:定义类体
CREATE OR REPLACE TYPE BODY emp_object AS MEMBER PROCEDURE change_dept_sal_proc(p_deptno NUMBER, p_percent NUMBER) AS BEGIN UPDATE emp SET sal=sal*(1 + p_percent) WHERE deptno=p_deptno ; END ; MEMBER FUNCTION get_sal_fun(p_empno NUMBER) RETURN NUMBER AS v_sal emp.sal%TYPE ; v_comm emp.comm%TYPE ; BEGIN SELECT sal,NVL(comm,0) INTO v_sal,v_comm FROM emp WHERE empno=p_empno ; RETURN v_sal + v_comm ; END; END ; / |
范例:声明对象并使用类
DECLARE v_emp emp_object ; BEGIN -- 实例化类对象 v_emp := emp_object(7369,800.0,20) ; -- 修改对象中atri_sal属性的内容 v_emp.atri_sal := 1000 ; -- 取得修改后的工资数额 DBMS_OUTPUT.put_line('7369雇员修改后的工资:' || v_emp.atri_sal) ; -- 通过对象调用类中的函数,取得7566雇员的工资 DBMS_OUTPUT.put_line('部门工资修改前,7566雇员的总工资:' || v_emp.get_sal_fun(7566)) ; -- 修改20部门雇员的工资,上涨30% v_emp.change_dept_sal_proc(20,0.3) ; -- 通过对象调用类中的函数,取得7566雇员的工资 DBMS_OUTPUT.put_line('部门工资修改后,7566雇员的总工资:' || v_emp.get_sal_fun(7566)) ; END ; / |
范例:删除emp_object类
DROP TYPE emp_object ; |
范例:使用两种不同的方式来定义函数
CREATE OR REPLACE TYPE emp_object AS OBJECT( atri_empno NUMBER(4) , -- 雇员编号 -- 修改当前雇员编号的工资,使用类中的empno和sal属性 MEMBER PROCEDURE change_emp_sal_proc(p_sal NUMBER) , -- 取得当前雇员的工资 MEMBER FUNCTION get_emp_sal_fun RETURN NUMBER , -- 修改指定部门的全体雇员工资 STATIC PROCEDURE change_dept_sal_proc(p_deptno NUMBER , p_sal NUMBER) , -- 取得此部门的工资总和 STATIC FUNCTION get_dept_sal_sum_fun(p_deptno NUMBER) RETURN NUMBER ) NOT FINAL ; / |
范例:定义类体实现类规范
CREATE OR REPLACE TYPE BODY emp_object AS MEMBER PROCEDURE change_emp_sal_proc(p_sal NUMBER) AS BEGIN -- 使用SELF.atri_empno找到本类中的属性,即:更新当前对象中雇员工资 UPDATE emp SET sal=p_sal WHERE empno=SELF.atri_empno ; END ; MEMBER FUNCTION get_emp_sal_fun RETURN NUMBER AS v_sal emp.sal%TYPE ; v_comm emp.comm%TYPE ; BEGIN -- 取得当前对象中指定雇员编号的工资 SELECT sal,NVL(comm,0) INTO v_sal,v_comm FROM emp WHERE empno=SELF.atri_empno ; RETURN v_sal + v_comm ; END ; STATIC PROCEDURE change_dept_sal_proc(p_deptno NUMBER , p_sal NUMBER) AS BEGIN -- 更新指定部门全部雇员的工资 UPDATE emp SET sal=p_sal WHERE deptno=p_deptno ; END ; STATIC FUNCTION get_dept_sal_sum_fun(p_deptno NUMBER) RETURN NUMBER AS v_sum NUMBER ; BEGIN -- 查询指定部门的工资总和 SELECT SUM(sal) INTO v_sum FROM emp WHERE deptno=p_deptno ; RETURN v_sum ; END ; END ; / |
范例:编写PL/SQL块实例化类对象
DECLARE v_emp emp_object ; BEGIN v_emp := emp_object(7369) ; -- 实例化emp_object类对象 v_emp.change_emp_sal_proc(3800) ; -- 修改7369工资 DBMS_OUTPUT.put_line('7369雇员工资:' || v_emp.get_emp_sal_fun()) ; DBMS_OUTPUT.put_line('10部门工资总和:' || emp_object.get_dept_sal_sum_fun(10)) ;-- 通过类调用 emp_object.change_dept_sal_proc(10,7000) ; -- 通过类调用 END ; / |
范例:定义类规范
CREATE OR REPLACE TYPE emp_object AS OBJECT( atri_empno NUMBER(4) , -- 雇员编号 atri_sal NUMBER(7,2) , -- 雇员工资 atri_comm NUMBER(7,2) , -- 雇员佣金 -- 定义构造函数,只接收雇员编号 CONSTRUCTOR FUNCTION emp_object(p_empno NUMBER) RETURN SELF AS RESULT , -- 重载构造函数,接收雇员编号及佣金 CONSTRUCTOR FUNCTION emp_object(p_empno NUMBER , p_comm NUMBER) RETURN SELF AS RESULT ) NOT FINAL ; / |
范例:定义类体,实现类规范
CREATE OR REPLACE TYPE BODY emp_object AS CONSTRUCTOR FUNCTION emp_object (p_empno NUMBER) RETURN SELF AS RESULT AS BEGIN SELF.atri_empno := p_empno ; -- 保存雇员编号属性 -- 查询指定雇员的工资,并将其内容赋值给atri_sal属性 SELECT sal INTO SELF.atri_sal FROM emp WHERE empno=p_empno ; RETURN ; END ; CONSTRUCTOR FUNCTION emp_object(p_empno NUMBER , p_comm NUMBER) RETURN SELF AS RESULT AS BEGIN SELF.atri_empno := p_empno ; SELF.atri_comm := p_comm ; SELF.atri_sal := 200.0 ; -- 为atri_sal设置默认值 RETURN ; END ; END ; / |
范例:使用PL/SQL块测试构造函数
DECLARE v_emp1 emp_object ; v_emp2 emp_object ; v_emp3 emp_object ; BEGIN v_emp1 := emp_object(7369,3500) ; -- 自定义构造函数 v_emp2 := emp_object(7566) ; -- 自定义构造函数 v_emp3 := emp_object(7839,0.0) ; -- 默认构造函数 DBMS_OUTPUT.put_line('7369雇员工资:' || v_emp1.atri_sal) ; DBMS_OUTPUT.put_line('7566雇员工资:' || v_emp2.atri_sal) ; DBMS_OUTPUT.put_line('7839雇员工资:' || v_emp3.atri_sal) ; END ; / |
范例:在类规范中定义MAP函数
CREATE OR REPLACE TYPE emp_object_map AS OBJECT( atri_empno NUMBER(4) , -- 雇员编号 atri_ename VARCHAR2(10) , -- 雇员姓名 atri_sal NUMBER(7,2) , -- 雇员工资 atri_comm NUMBER(7,2) , -- 雇员佣金 -- 定义MAP函数,此函数会在进行排序时自动调用 MAP MEMBER FUNCTION compare RETURN NUMBER ) NOT FINAL ; / |
范例:定义类体实现MAP函数
CREATE OR REPLACE TYPE BODY emp_object_map AS MAP MEMBER FUNCTION compare RETURN NUMBER AS BEGIN RETURN SELF.atri_sal + SELF.atri_comm ; END ; END ; / |
范例:编写数据库创建脚本
-- 按照emp_object_map的结构创建一张新的数据表,这样就可以使用MAP函数进行排序 CREATE TABLE emp_object_map_tab OF emp_object_map ; INSERT INTO emp_object_map_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7369,'SMITH',800,0) ; INSERT INTO emp_object_map_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7902,'FORD',3000,0) ; INSERT INTO emp_object_map_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7499,'ALLEN',1600,300) ; INSERT INTO emp_object_map_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7521,'WARD',1250,500) ; INSERT INTO emp_object_map_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7839,'KING',5000,0) ; COMMIT ; |
范例:通过查询实现排序
SELECT VALUE(e) ve , e.atri_empno , e.atri_ename , e.atri_sal+e.atri_comm FROM emp_object_map_tab e ORDER BY ve ; |
范例:定义类规范使用ORDER定义函数
CREATE OR REPLACE TYPE emp_object_order AS OBJECT( atri_empno NUMBER(4) , -- 雇员编号 atri_ename VARCHAR2(10) , -- 雇员姓名 atri_sal NUMBER(7,2) , -- 雇员工资 atri_comm NUMBER(7,2) , -- 雇员佣金 -- 定义ORDER函数,此函数可以用于两个对象间的比较 ORDER MEMBER FUNCTION compare(obj emp_object_order) RETURN NUMBER ) NOT FINAL ; / |
范例:定义类体实现ORDER函数
CREATE OR REPLACE TYPE BODY emp_object_order AS ORDER MEMBER FUNCTION compare(obj emp_object_order) RETURN NUMBER AS BEGIN IF (SELF.atri_sal + SELF.atri_comm) > (obj.atri_sal + obj.atri_comm) THEN RETURN 1 ; ELSIF (SELF.atri_sal + SELF.atri_comm) < (obj.atri_sal + obj.atri_comm) THEN RETURN -1 ; ELSE RETURN 0 ; END IF ; END ; END ; / |
范例:定义PL/SQL块进行对象排序
DECLARE v_emp1 emp_object_order ; v_emp2 emp_object_order ; BEGIN v_emp1 := emp_object_order(7499,'ALLEN',1600,300) ; v_emp2 := emp_object_order(7521,'WARD',1250,500) ; IF v_emp1 > v_emp2 THEN DBMS_OUTPUT.put_line('7499的工资高于7521的工资。') ; ELSIF v_emp1 < v_emp2 THEN DBMS_OUTPUT.put_line('7499的工资低于7521的工资。') ; ELSE DBMS_OUTPUT.put_line('7499的工资与7521的工资相同。') ; END IF ; END ; / |
范例:创建数据表
-- 根据emp_object_order创建数据表 CREATE TABLE emp_object_order_tab OF emp_object_order ; INSERT INTO emp_object_order_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7369,'SMITH',800,0) ; INSERT INTO emp_object_order_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7902,'FORD',3000,0) ; INSERT INTO emp_object_order_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7499,'ALLEN',1600,300) ; INSERT INTO emp_object_order_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7521,'WARD',1250,500) ; INSERT INTO emp_object_order_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7839,'KING',5000,0) ; COMMIT ; |
范例:进行数据查询,同时使用ORDER BY排序
SELECT VALUE(e) ve , e.atri_empno , e.atri_ename , e.atri_sal+e.atri_comm FROM emp_object_order_tab e ORDER BY ve ; |
范例:定义类规范
-- 删除emp_object DROP TYPE emp_object ; -- 定义部门类 CREATE OR REPLACE TYPE dept_object AS OBJECT ( atri_deptno NUMBER(2) , -- 部门编号 atri_dname VARCHAR2(14) , -- 部门名称 atri_loc VARCHAR2(13) , -- 部门位置 -- 取得对象信息 MEMBER FUNCTION tostring RETURN VARCHAR2 ) NOT FINAL ; / -- 定义雇员类,每一个雇员属于一个部门,所以设置了一个atri_dept的属性 CREATE OR REPLACE TYPE emp_object AS OBJECT( atri_empno NUMBER(4) , -- 雇员编号 atri_ename VARCHAR2(10) , -- 雇员姓名 atri_job VARCHAR2(9) , -- 雇员职位 atri_hiredate DATE , -- 雇佣日期 atri_sal NUMBER(7,2) , -- 雇员工资 atri_comm NUMBER(7,2) , -- 雇员佣金 atri_dept dept_object , -- 雇员部门 -- 取得对象信息 MEMBER FUNCTION tostring RETURN VARCHAR2 ) NOT FINAL ; / |
范例:定义类体实现类规范
-- 定义dept_object类体 CREATE OR REPLACE TYPE BODY dept_object AS MEMBER FUNCTION tostring RETURN VARCHAR2 AS BEGIN RETURN '部门编号:' || SELF.atri_deptno || ',名称:' || SELF.atri_dname || ',位置:' || SELF.atri_loc ; END ; END ; / -- 定义emp_object类体 CREATE OR REPLACE TYPE BODY emp_object AS MEMBER FUNCTION tostring RETURN VARCHAR2 AS BEGIN RETURN '雇员编号:' || SELF.atri_empno || ',姓名:' || SELF.atri_ename || ',职位:' || SELF.atri_job || ',雇佣日期:' || TO_CHAR(SELF.atri_hiredate,'yyyy-mm-dd') || ',工资:' || SELF.atri_sal || ',佣金:' || SELF.atri_comm ; END ; END ; / |
范例:编写PL/SQL块验证关系
DECLARE v_dept dept_object ; v_emp emp_object ; BEGIN -- 首先定义部门对象,此对象需要通过emp_object类的构造方法保存到v_emp对象属性之中 v_dept := dept_object(10,'ACCOUNTING','NEW YORK') ; -- 定义雇员对象,传递此雇员所属的部门对象 v_emp := emp_object(7839,'KING','PRESIDENT',TO_DATE('1981-11-11','yyyy-mm-dd'),5000,null,v_dept) ; -- 直接输出雇员的完整信息 DBMS_OUTPUT.put_line(v_emp.tostring()) ; -- 根据信息找到其对应的部门信息 DBMS_OUTPUT.put_line(v_emp.atri_dept.tostring()) ; END ; / |
范例:定义父类 —— person_object
-- 定义Person类规范 CREATE OR REPLACE TYPE person_object AS OBJECT ( atri_pid NUMBER , -- 人员编号 atri_name VARCHAR2(10) , -- 人员姓名 atri_sex VARCHAR2(10) , -- 人员性别 MEMBER FUNCTION get_person_info_fun RETURN VARCHAR2 ) NOT FINAL ; / -- 定义Person类体 CREATE OR REPLACE TYPE BODY person_object AS MEMBER FUNCTION get_person_info_fun RETURN VARCHAR2 AS BEGIN RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex ; END ; END ; / |
范例:定义子类 —— emp_object
-- 定义Emp类规范,此类为Person子类 CREATE OR REPLACE TYPE emp_object UNDER person_object ( atri_job VARCHAR2(9) , -- 雇员职位 atri_sal NUMBER(7,2) , -- 雇员工资 atri_comm NUMBER(7,2) , -- 雇员佣金 MEMBER FUNCTION get_emp_info_fun RETURN VARCHAR2 ) ; / -- 定义Emp类体 CREATE OR REPLACE TYPE BODY emp_object AS MEMBER FUNCTION get_emp_info_fun RETURN VARCHAR2 AS BEGIN RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex || ',职位:' || SELF.atri_job || ',工资:' || SELF.atri_sal || ',佣金:' || SELF.atri_comm ; END ; END ; / |
范例:利用PL/SQL程序块测试
DECLARE v_emp emp_object ; BEGIN -- 此处必须明确写出父类与子类的全部参数 -- person_object类需要传入三个参数:人员编号、姓名、性别 -- emp_object类需要传入三个参数:职位、工资、佣金 v_emp := emp_object(7369,'SMITH','FEMALE','CLERK',800.0,0.0) ; DBMS_OUTPUT.put_line('person_object类的函数:' || v_emp.get_person_info_fun()) ; DBMS_OUTPUT.put_line('emp_object类的函数:' || v_emp.get_emp_info_fun()) ; END ; / |
|
程序运行结果: |
person_object类的函数:人员编号:7369,姓名:SMITH,性别:FEMALE emp_object类的函数:人员编号:7369,姓名:SMITH,性别:FEMALE,职位:CLERK,工资:800,佣金:0 |
范例:定义程序,实现函数的覆写
-- 定义Person类规范 CREATE OR REPLACE TYPE person_object AS OBJECT ( atri_pid NUMBER , -- 人员编号 atri_name VARCHAR2(10) , -- 人员姓名 atri_sex VARCHAR2(10) , -- 人员性别 MEMBER FUNCTION tostring RETURN VARCHAR2 ) NOT FINAL ; / -- 定义Person类体 CREATE OR REPLACE TYPE BODY person_object AS MEMBER FUNCTION tostring RETURN VARCHAR2 AS BEGIN RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex ; END ; END ; / -- 定义Emp类规范,此类为Person子类 CREATE OR REPLACE TYPE emp_object UNDER person_object ( atri_job VARCHAR2(9) , -- 雇员职位 atri_sal NUMBER(7,2) , -- 雇员工资 atri_comm NUMBER(7,2) , -- 雇员佣金 -- 此函数名称与父类函数名称一样,所以此处为函数的覆写 OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 ) ; / -- 定义Emp类体 CREATE OR REPLACE TYPE BODY emp_object AS OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 AS BEGIN RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex || '职位:' || SELF.atri_job || ',工资:' || SELF.atri_sal || ',佣金:' || SELF.atri_comm ; END ; END ; / |
范例:编写PL/SQL块测试程序
DECLARE v_emp emp_object ; BEGIN -- 此处必须明确写出父类与子类的全部参数 -- person_object类需要传入三个参数:人员编号、姓名、性别 -- emp_object类需要传入三个参数:职位、工资、佣金 v_emp := emp_object(7369,'SMITH','FEMALE','CLERK',800.0,0.0) ; DBMS_OUTPUT.put_line(v_emp.tostring()) ; END ; / |
范例:在原有程序基础上增加新的子类
-- 定义Person类规范 CREATE OR REPLACE TYPE person_object AS OBJECT ( atri_pid NUMBER , -- 人员编号 atri_name VARCHAR2(10) , -- 人员姓名 atri_sex VARCHAR2(10) , -- 人员性别 MEMBER FUNCTION tostring RETURN VARCHAR2 ) NOT FINAL ; / -- 定义Person类体 CREATE OR REPLACE TYPE BODY person_object AS MEMBER FUNCTION tostring RETURN VARCHAR2 AS BEGIN RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex ; END ; END ; / -- 定义Emp类规范,此类为Person子类 CREATE OR REPLACE TYPE emp_object UNDER person_object ( atri_job VARCHAR2(9) , -- 雇员职位 atri_sal NUMBER(7,2) , -- 雇员工资 atri_comm NUMBER(7,2) , -- 雇员佣金 -- 此函数名称与父类函数名称一样,所以此处为函数的覆写 OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 ) ; / -- 定义Emp类体 CREATE OR REPLACE TYPE BODY emp_object AS OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 AS BEGIN RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex || '职位:' || SELF.atri_job || ',工资:' || SELF.atri_sal || ',佣金:' || SELF.atri_comm ; END ; END ; / -- 定义Student类规范,此类为Person子类 CREATE OR REPLACE TYPE student_object UNDER person_object( atri_schoolVARCHAR2(15) , atri_scoreNUMBER(5,2) , OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 ) ; / -- 定义Student类体 CREATE OR REPLACE TYPE BODY student_object AS OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 AS BEGIN RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex || '学校:' || SELF.atri_school || ',成绩:' || SELF.atri_score ; END ; END ; / |
范例:通过两个子类为person_object类对象实例化
DECLARE v_emp person_object ; -- 声明person_object类对象 v_student person_object ; -- 声明person_object类对象 BEGIN -- 对象向上转型 v_emp := emp_object(7369,'SMITH','FEMALE','CLERK',800.0,0.0) ; v_student := student_object(7566,'ALLEN','FEMALE','MLDN',99.9) ; DBMS_OUTPUT.put_line('【雇员信息】' || v_emp.tostring()) ; DBMS_OUTPUT.put_line('【学生信息】' || v_student.tostring()) ; END ; / |
范例:使用FINAL定义的类不能被继承
-- 定义Person类规范 CREATE OR REPLACE TYPE person_object AS OBJECT ( atri_pid NUMBER ) FINAL ; -- 不管是否写此句默认均为FINAL / -- 定义Emp类规范,但是此时由于person_object类无法继承,所以出现错误 CREATE OR REPLACE TYPE emp_object UNDER person_object ( atri_job VARCHAR2(9) ) ; / |
范例:使用FINAL定义的函数不能被子类覆写
-- 定义Person类规范 CREATE OR REPLACE TYPE person_object AS OBJECT ( atri_pid NUMBER , FINAL MEMBER FUNCTION tostring RETURN VARCHAR2 ) NOT FINAL ; -- 不管是否写此句默认均为FINAL / -- 定义Emp类规范,但是此时由于person_object类无法继承,所以出现错误 CREATE OR REPLACE TYPE emp_object UNDER person_object ( atri_job VARCHAR2(9) , -- 错误:此处无法覆写tostring()函数 OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 ) ; / |
范例:定义抽象类与抽象函数
DROP TYPE emp_object ; -- 定义Person类规范 CREATE OR REPLACE TYPE person_object AS OBJECT ( atri_pid NUMBER , -- 人员编号 atri_name VARCHAR2(10) , -- 人员姓名 atri_sex VARCHAR2(10) , -- 人员性别 NOT INSTANTIABLE MEMBER FUNCTION tostring RETURN VARCHAR2 -- 定义抽象方法 ) NOT FINAL NOT INSTANTIABLE ; -- 此处必须使用NOT INSTANTIABLE声明类 / -- 定义Emp类规范,此类为Person子类 CREATE OR REPLACE TYPE emp_object UNDER person_object ( atri_job VARCHAR2(9) , -- 雇员职位 atri_sal NUMBER(7,2) , -- 雇员工资 atri_comm NUMBER(7,2) , -- 雇员佣金 -- 此函数名称与父类函数名称一样,所以此处为函数的覆写 OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 ) ; / -- 定义Emp类体 CREATE OR REPLACE TYPE BODY emp_object AS OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 AS BEGIN RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex || '职位:' || SELF.atri_job || ',工资:' || SELF.atri_sal || ',佣金:' || SELF.atri_comm ; END ; END ; / |
范例:编写程序进行测试
DECLARE v_emp person_object ; BEGIN -- 通过子类对象为父类实例化 v_emp := emp_object(7369,'SMITH','FEMALE','CLERK',800.0,0.0) ; DBMS_OUTPUT.put_line(v_emp.tostring()) ; END ; / |
范例:定义要使用的类结构
-- 删除emp_object,否则dept_object无法重新建立 DROP TYPE emp_object ; -- 定义部门类 CREATE OR REPLACE TYPE dept_object AS OBJECT ( atri_deptno NUMBER(2) , -- 部门编号 atri_dname VARCHAR2(14) , -- 部门名称 atri_loc VARCHAR2(13) , -- 部门位置 -- 取得对象信息 MEMBER FUNCTION tostring RETURN VARCHAR2 ) NOT FINAL ; / -- 定义Person类规范 CREATE OR REPLACE TYPE person_object AS OBJECT ( atri_pid NUMBER , -- 人员编号 atri_name VARCHAR2(10) , -- 人员姓名 atri_sex VARCHAR2(10) , -- 人员性别 NOT INSTANTIABLE MEMBER FUNCTION tostring RETURN VARCHAR2 , -- 定义抽象方法 -- 实现对象排序 NOT INSTANTIABLE MAP MEMBER FUNCTION compare RETURN NUMBER ) NOT FINAL NOT INSTANTIABLE ; -- 此处必须使用NOT INSTANTIABLE声明类 / -- 定义Emp类规范,此类为Person子类 CREATE OR REPLACE TYPE emp_object UNDER person_object ( atri_job VARCHAR2(9) , -- 雇员职位 atri_sal NUMBER(7,2) , -- 雇员工资 atri_comm NUMBER(7,2) , -- 雇员佣金 atri_dept dept_object , -- 雇员部门 -- 此函数名称与父类函数名称一样,所以此处为函数的覆写 OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 , -- 实现对象排序 OVERRIDING MAP MEMBER FUNCTION compare RETURN NUMBER ) ; / -- 定义dept_object类体 CREATE OR REPLACE TYPE BODY dept_object AS MEMBER FUNCTION tostring RETURN VARCHAR2 AS BEGIN RETURN '部门编号:' || SELF.atri_deptno || ',名称:' || SELF.atri_dname || ',位置:' || SELF.atri_loc ; END ; END ; / -- 定义emp_object类体 CREATE OR REPLACE TYPE BODY emp_object AS OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 AS BEGIN RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex || '职位:' || SELF.atri_job || ',工资:' || SELF.atri_sal || ',佣金:' || SELF.atri_comm ; END ; OVERRIDING MAP MEMBER FUNCTION compare RETURN NUMBER AS BEGIN RETURN SELF.atri_sal + SELF.atri_comm ; END ; END ; / |
范例:创建一个对象表
CREATE TABLE emp_object_tab OF emp_object ; |
范例:查看emp_object_tab数据表结构
DESC emp_object_tab ; |
范例:使用类创建表中的列
CREATE TABLE myemp_tab ( empno NUMBER(4) , ename VARCHAR2(20) , dept dept_object ) ; |
范例:增加数据,但是不增加部门属性数据
INSERT INTO emp_object_tab(atri_pid,atri_name,atri_sex,atri_job,atri_sal,atri_comm) VALUES (10,'李兴华','男','办事员',3500,100); |
范例:增加数据,同时使用嵌套类型
INSERT INTO emp_object_tab(atri_pid,atri_name,atri_sex,atri_job,atri_sal,atri_comm,atri_dept) VALUES (20,'马云涛','男','技术员',5500,200, dept_object(10,'开发部','北京')); |
范例:查询emp_object_tab表中的全部数据
SELECT * FROM emp_object_tab ; |
范例:数据排序显示
SELECT VALUE(e) ve , atri_pid , atri_name , atri_sex , atri_job, atri_sal , atri_comm FROM emp_object_tab e ORDER BY ve DESC ; |
范例:查询单条数据并将数据设置给person_object类对象
DECLARE v_emp emp_object ; BEGIN -- 查询指定人员的信息,并将此信息转变为对象 SELECT VALUE(e) INTO v_emp FROM emp_object_tab e WHERE e.atri_pid=20 ; -- 输出雇员信息 DBMS_OUTPUT.put_line(v_emp.tostring()) ; -- 输出雇员所在部门信息 DBMS_OUTPUT.put_line(v_emp.atri_dept.tostring()) ; END ; / |
范例:利用游标来接收多条返回结果
DECLARE v_emp emp_object ; CURSOR cur_emp IS SELECT VALUE(e) ve FROM emp_object_tab e ; BEGIN FOR v_emprow IN cur_emp LOOP v_emp := v_emprow.ve ;-- 取出一个雇员信息 DBMS_OUTPUT.put_line(v_emp.tostring()) ; IF v_emp.atri_dept IS NOT NULL THEN DBMS_OUTPUT.put_line('雇员部门 --> ' || v_emp.atri_dept.tostring()) ; END IF ; END LOOP ; END ; / |
范例:定义person_object新的子类emp_object_ref,此类对dept_object通过REF定义嵌套关系
-- 定义Emp类规范,此类为Person子类 CREATE OR REPLACE TYPE emp_object_ref UNDER person_object ( atri_job VARCHAR2(9) , -- 雇员职位 atri_sal NUMBER(7,2) , -- 雇员工资 atri_comm NUMBER(7,2) , -- 雇员佣金 atri_deptREF dept_object , -- 雇员部门 -- 此函数名称与父类函数名称一样,所以此处为函数的覆写 OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 , -- 实现对象排序 OVERRIDING MAP MEMBER FUNCTION compare RETURN NUMBER ) ; / -- 定义emp_object类体 CREATE OR REPLACE TYPE BODY emp_object_ref AS OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 AS BEGIN RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex || '职位:' || SELF.atri_job || ',工资:' || SELF.atri_sal || ',佣金:' || SELF.atri_comm ; END ; OVERRIDING MAP MEMBER FUNCTION compare RETURN NUMBER AS BEGIN RETURN SELF.atri_sal + SELF.atri_comm ; END ; END ; / |
范例:创建emp_object_ref与dept_object_ref对象表
CREATE TABLE emp_object_ref_tab OF emp_object_ref ; CREATE TABLE dept_object_ref_tab OF dept_object ; |
范例:向dept_object_ref对象表中增加数据
INSERT INTO dept_object_ref_tab (atri_deptno , atri_dname , atri_loc) VALUES (10,'MLDN教学','北京') ; INSERT INTO dept_object_ref_tab (atri_deptno , atri_dname , atri_loc) VALUES (20,'MLDN研发','北京') ; INSERT INTO dept_object_ref_tab (atri_deptno , atri_dname , atri_loc) VALUES (30,'MLDN移动','美国') ; |
范例:查询dept_object_ref_tab数据表
SELECT * FROM dept_object_ref_tab ; |
范例:向emp_object_ref_tab表中增加数据
INSERT INTO emp_object_ref_tab(atri_pid,atri_name,atri_sex,atri_job,atri_sal,atri_comm,atri_dept) VALUES (3010,'李兴华','男','办事员',3500,100,( SELECT REF(d) FROM dept_object_ref_tab d WHERE atri_deptno=10)); INSERT INTO emp_object_ref_tab(atri_pid,atri_name,atri_sex,atri_job,atri_sal,atri_comm,atri_dept) VALUES (3020,'马云涛','男','技术员',5500,200,( SELECT REF(d) FROM dept_object_ref_tab d WHERE atri_deptno=20)); |
范例:查询emp_object_ref_tab数据表
SELECT * FROM emp_object_ref_tab ; |
范例:利用DEREF()函数查看REF引用数据信息
SELECT atri_pid,atri_name,atri_sex,atri_job,atri_sal,atri_comm, DEREF(atri_dept) dept FROM emp_object_ref_tab ; |
范例:更新emp_object_tab对象表(此表不使用REF引用)中的部门信息
UPDATE emp_object_tab SET atri_job='经理' , atri_dept=dept_object(30,'魔乐','加拿大') WHERE atri_pid=10 ; |
范例:查询emp_object_tab对象表中修改后的数据
SELECT * FROM emp_object_tab WHERE atri_pid=10 ; |
范例:更新emp_object_ref_tab对象表(此表使用REF引用)中的部门信息
UPDATE emp_object_ref_tab SET atri_dept=( SELECT REF(d) FROM dept_object_ref_tab d WHERE atri_deptno=30) WHERE atri_pid=3020 ; |
范例:查询emp_object_ref_tab对象表中修改后的数据
SELECT atri_pid,atri_name,atri_sex,atri_job,atri_sal,atri_comm, DEREF(atri_dept) dept FROM emp_object_ref_tab WHERE atri_pid=3020 ; |
范例:更新emp_object_ref_tab对象表中所有10部门雇员信息
UPDATE emp_object_ref_tab SET atri_name='王月清',atri_sal=6000 WHERE atri_dept=(SELECT REF(d) FROM dept_object_ref_tab d WHERE atri_deptno=10) ; |
范例:查询emp_object_ref_tab数据表的数据
SELECT atri_pid,atri_name,atri_sex,atri_job,atri_sal,atri_comm, DEREF(atri_dept) dept FROM emp_object_ref_tab ; |
范例:删除emp_object_ref_tab表中10部门的雇员信息
DELETE FROM emp_object_ref_tab WHERE atri_dept=(SELECT REF(d) FROM dept_object_ref_tab d WHERE atri_deptno=10) ; |
范例:查询emp_object_ref_tab数据表的数据
SELECT atri_pid,atri_name,atri_sex,atri_job,atri_sal,atri_comm, DEREF(atri_dept) dept FROM emp_object_ref_tab ; |
范例:定义类,此类的结构与emp表结构一致
CREATE OR REPLACE TYPE emp_table_object AS OBJECT ( atri_empno NUMBER(4) , atri_ename VARCHAR2(10) , atri_job VARCHAR2(9) , atri_mgr NUMBER(4) , atri_hiredate DATE , atri_sal NUMBER(7,2) , atri_comm NUMBER(7,2) , atri_deptno NUMBER(2) , MEMBER FUNCTION tostring RETURN VARCHAR2 ) NOT FINAL ; / CREATE OR REPLACE TYPE BODY emp_table_object AS MEMBER FUNCTION tostring RETURN VARCHAR2 AS BEGIN RETURN '雇员编号:' || SELF.atri_empno || ',姓名:' || SELF.atri_ename || ',职位:' || SELF.atri_job || ',雇佣日期:' || SELF.atri_hiredate || ',工资:' || SELF.atri_sal || ',佣金:' || SELF.atri_comm ; END ; END ; / |
范例:创建对象视图
CREATE OR REPLACE VIEW v_myview OF emp_table_object WITH OBJECT IDENTIFIER(atri_empno) AS SELECT empno,ename,job,mgr,hiredate,sal,comm,deptno FROM emp ; |
范例:编写PL/SQL访问视图
DECLARE v_emp emp_table_object ; BEGIN SELECT VALUE(ev) INTO v_emp FROM v_myview ev WHERE atri_empno=7839 ; DBMS_OUTPUT.put_line(v_emp.tostring()) ; END ; / |