Oracle对象类型 (转)

本文详细介绍了Oracle数据库中的对象类型概念,包括如何创建简单的对象类型、带有方法的对象类型以及对象类型表。通过具体示例展示了对象类型的应用场景,比如构造函数、映射方法和排序方法的使用。
Oracle对象类型也有属性方法
  创建对象类型与创建表很相似,只是实际上不为存储的数据分配空间:

  不带方法的简单对象类型:

CREATE TYPE type_name as OBJECT (
column_1 type1,
column_2 type2,
...
);

  注意:AS OBJECT

  创建好对象类型之后,就可以在创建表的时候,使用该类型了,如:

CREATE TYPE HUMAN AS OBJECT(
NAME VARCHAR2(20),
SEX VARCHAR2(1),-- F : FEMALE M:MALE
BIRTHDAY DATE,
NOTE VARCHAR2(300)
)


  稍后,可以用下面的语句查看:

SELECT * FROM USER_OBJECTS WHERE OBJECT_TYPE = 'TYPE'
CREATE TABLE STUDENTS(
GUID NUMBER NOT NULL,
STUDENTS HUMAN)

  此下省去两个Trigger.
  插入数据的时候,可以如下:

INSERT INTO STUDENTS (STUDENT) VALUES (HUMAN('xling','M',TO_DATE('20060101','YYYYMMDD'),'测试'))


  注意:HUMAN('xling','M',TO_DATE('20060101','YYYYMMDD'),'测试'),这是个默认的构造函数.
  如果想选出性别为女(F)的记录,可以如下:

SELECT * FROM STUDENTS S WHERE S.STUDENT.SEX = 'F'


  注意:不能写成:SELECT * FROM STUDENTS WHERE STUDENT.SEX = 'F' 这样会报如下错误:ORA-00904: "STUDENT"."SEX": 标识符无效


  对象类型表:每条记录都是对象的表,称为对象类型表.它有两个使用方法:1,用作只有一个对象类型字段的表.2,用作具有对象类型字段的标准关系表.
  语法如下:

CREATE TABLE table_name OF object_type;


  例如:

CREATE TABLE TMP_STUDENTS OF HUMAN;


  用DESC TMP_STUDENTS,可以看到它的字段结构和HUMAN的结构一样.
  对象类型表有两个优点:1,从某种程度上简化了对象的使用,因为对象表的字段类型与对象类型是一致的,所以,不需要用对象名来修饰对象属性,可以把数据插入对象类型表,就像插入普通的关系表中一样:

INSERT INTO TMP_STUDENTS VALUES ('xling','M',TO_DATE('20060601','YYYYMMDD'),'对象类型表');
  当然也可用如下方法插入:
INSERT INTO TMP_STUDENTS VALUES (HUMAN('snow','F',TO_DATE('20060102','YYYYMMDD'),'用类型的构造函数'));

  第二个特点是:对象表是使用对象类型作为模板来创建表的一种便捷方式,它可以确保多个表具有相同的结构.

  对象类型表在:USER_TABLES表里是查不到的,而在USER_OBJECTS表里可以查到,而且OBJECT_TYPE = 'TABLE'

  类型在定义的时候,会自动包含一个方法,即默认的构造器.构造器的名称与对象的名称相同,它带有变量与对象类型的每个属性相对应.


  对象类型的方法:

CREATE TYPE type_name AS OBJECT (
column1 column_type1,
column2 column_type2,
... ,
MEMBER FUNCTION method_name(args_list) RETURN return_type,
...
)

  注意:是MEMBER FUNCTION,(当然,也可是MEMBER PROCEDURE,没有返回值)

  和包(PACKAGE)一样,如果对象类型有方法的话,还要声明一个BODY:

CREATE TYPE BODY type_name AS

MEMBER FUNCTION method_name RETURN return_type {AS | IS}
variable declareations..
BEGIN
CODE..
RETURN return_value;
END;//END MEMBER FUNCTION
...
END;//END TYPE BODY

  如下所示:

CREATE TYPE HUMAN AS OBJECT(
NAME VARCHAR2(20),
SEX VARCHAR2(1),-- F : FEMALE M:MALE
BIRTHDAY DATE,
NOTE VARCHAR2(300),

MEMBER FUNCTION GET_AGE RETURN NUMBER
)

--BODY
CREATE TYPE BODY HUMAN AS
MEMBER FUNCTION GET_AGE RETURN NUMBER AS
V_MONTHS NUMBER;
BEGIN
SELECT FLOOR(MONTHS_BETWEEN(SYSDATE,BIRTHDAY)/12) INTO V_MONTHS FROM DUAL;
RETURN V_MONTHS;
END;
END;


  
  注意:BODY的格式,不是AS OBJECT,也不是用小括号括起来的.MEMBER FUNCTION 后的AS或IS不能省略.
  还以STUDENTS表为例(注:如果类型以被某个表使用,是不能修改的,必须把相关的表删除,然后把类型删除,在一个一个新建,这里就省略了,参见前文所述)

SELECT S.STUDENT.GET_AGE() FROM STUDENTS S


  
  在提起注意:表名一定要有别名.GET_AGE()的括号不能省略,否则会提示错误.

  下面演示在一个匿名过程中的使用情况:

SET SERVEROUTPUT ON
DECLARE
AA HUMAN;
AGE NUMBER;
BEGIN
AA := HUMAN('xingFairy','M',TO_DATE('19830714','YYYYMMDD'),'过程');
AGE := AA.GET_AGE();
DBMS_OUTPUT.PUT_LINE(AGE);
END;

  映射方法:
  映射方法是一种不带参数,并返回标准的标量Oracle SQL数据类型的方法,如NUMBER,VARCHAR2,Oracle将间接地使用这些方法执行比较运算.
  映射方法最重要的一个特点是:当在WHERE或ORDER BY等比较关系子句中使用对象时,会间接地使用映射方法.
  映射方法的声明只过是在普通方法声明的前面加一个 MAP而以,注意:映射方法是一种不带参数的方法.
MAP MEMBER FUNCTION function_name RETURN return_type

  修改前文提到的HUMAN类型:
--映射方法 MAP

CREATE TYPE HUMAN AS OBJECT(
NAME VARCHAR2(20),
SEX VARCHAR2(1),-- F : FEMALE M:MALE
BIRTHDAY DATE,--注册日期 
REGISTERDAY DATE,
NOTE VARCHAR2(300),

MEMBER FUNCTION GET_AGE RETURN NUMBER,
MAP MEMBER FUNCTION GET_GRADE RETURN NUMBER
)

CREATE TYPE BODY HUMAN AS
-----------------------
MEMBER FUNCTION GET_AGE RETURN NUMBER AS
V_MONTHS NUMBER;
BEGIN
SELECT FLOOR(MONTHS_BETWEEN(SYSDATE,BIRTHDAY)/12) INTO V_MONTHS FROM DUAL;
RETURN V_MONTHS;
END;
------------------------
MAP MEMBER FUNCTION GET_GRADE RETURN NUMBER AS
BEGIN
RETURN MONTHS_BETWEEN(SYSDATE,BIRTHDAY);
END;
END;

  插入数据:

INSERT INTO STUDENTS (STUDENT) VALUES (HUMAN('xling','M',TO_DATE('19830714','YYYYMMDD'),TO_DATE('20020915','YYYYMMDD'), '测试MAP方法'));
INSERT INTO STUDENTS (STUDENT) VALUES (HUMAN('fairy','M',TO_DATE('19830714','YYYYMMDD'),TO_DATE('20010915','YYYYMMDD'), '测试MAP方法'));
INSERT INTO STUDENTS (STUDENT) VALUES (HUMAN('snow','M',TO_DATE('19830714','YYYYMMDD'),TO_DATE('20020915','YYYYMMDD'), '测试MAP方法'));

  在执行上面的操作后,用下面这个SELECT语句可以看出映射方法的效果:
SELECT S.STUDENT.NAME,S.STUDENT.GET_GRADE() FROM STUDENTS S ORDER BY STUDENT
  它是按MAP方法GET_GRADE()的值进行排序的.注意是ORDER BY STUDENT,在提起一次需要注意,一定要用表的别名,方法后的括号不能省略,即使没有参数.
  如果想以MAP方法的结果为条件,可以如下:

SELECT S.STUDENT.NAME,S.STUDENT.GET_GRADE() FROM STUDENTS S WHERE S.STUDENT.GET_GRADE() > 50
SELECT S.STUDENT.NAME,S.STUDENT.GET_GRADE() FROM STUDENTS S WHERE STUDENT > HUMAN(NULL,NULL,NULL,TO_DATE('20020101','YYYYMMDD'),NULL);


  排序方法:
  先说一下SELF,Oracle里对象的SELF和JAVA里的this是同一个意思.
  对象的排序方法具有一个与对象类型相同的参数,暂称为ARG1,用于和SELF对象进行比较.如果调用方法的SELF对象比ARG1小,返回负值,如果相等,返回0,如果SELF大于ARG1,则返回值大于0.

--映射方法 MAP

CREATE TYPE HUMAN AS OBJECT(
NAME VARCHAR2(20),
SEX VARCHAR2(1),-- F : FEMALE M:MALE
BIRTHDAY DATE,
REGISTERDAY DATE,
NOTE VARCHAR2(300),

MEMBER FUNCTION GET_AGE RETURN NUMBER,
ORDER MEMBER FUNCTION MATCH(I_STUDENT IN HUMAN) RETURN NUMBER
)

CREATE TYPE BODY HUMAN AS
-----------------------
MEMBER FUNCTION GET_AGE RETURN NUMBER AS
V_MONTHS NUMBER;
BEGIN
SELECT FLOOR(MONTHS_BETWEEN(SYSDATE,BIRTHDAY)/12) INTO V_MONTHS FROM DUAL;
RETURN V_MONTHS;
END;
------------------------
ORDER MEMBER FUNCTION MATCH(I_STUDENT IN HUMAN) RETURN NUMBER AS
BEGIN
RETURN REGISTERDAY - I_STUDENT.REGISTERDAY;
END;
END;

  注意:在声明的时候,ORDER方法的参数类型要和SELF的类型一致.

SET SERVEROUTPUT ON
DECLARE
S1 HUMAN;
S2 HUMAN;
BEGIN

S1 := HUMAN('xling',NULL,NULL,TO_DATE('20020915','YYYYMMDD'),NULL);
S2 := HUMAN('snow',NULL,NULL,TO_DATE('20010915','YYYYMMDD'),NULL);

IF S1 > S2 THEN
DBMS_OUTPUT.PUT_LINE(S1.NAME);
ELSIF S1 < S2 THEN
DBMS_OUTPUT.PUT_LINE(S2.NAME);
ELSE
DBMS_OUTPUT.PUT_LINE('EQUAL');
END IF;
END;

  注意S1 和 S2是怎么比较的.

  映射方法具有效率方面的优势,因为它把每个对象与单个标量值联系在一起;排序方法有灵活方面的优势,它可以在两个对象之间进行任意复杂的比较.排序方法比映射方法的速度慢.
[@more@]

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/9650775/viewspace-923304/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/9650775/viewspace-923304/

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值