Oracle自定义数据类型

Oracle数据库中的数据类型 Oracle数据库不仅支持常规的内置数据类型,还支持用户定义的数据类型,包括对象类型(Object Type)、嵌套类型(Nested Table Type)和可变数组类型(Varray Data Type)。用于存储二进制格式的数据,通常用于存储GUID、MD5值等不进行字符集转换的数据。是可变长度的字符类型,存储的长度与实际字符长度相同,最多可以存储4000个字符(Oracle 11g之前)。是固定长度的字符类型,即使存储的字符长度不足定义的长度,数据库也会在末尾填充空格至指定长度。 阅读详情

注:为了更加清晰的看清有些没有格式的SQL语句,本人修改了原文作者文章的部分sql格式

因不知原文出处,链接就不附带了...望体谅


一:Oracle中的类型有很多种,主要可以分为以下几类:

1、字符串类型。如:char、nchar、varchar2、nvarchar2。
2、数值类型。如:int、number(p,s)、integer、smallint。
3、日期类型。如:date、interval、timestamp。
4、PL/SQL类型。如:pls_integer、binary_integer、binary_double(10g)、binary_float(10g)、boolean。plsql类型是不能在sql环境中使用的,比如建表时。
5、自定义类型:type / create type。

二:type / create type 区别联系

相同:

可用用关键字create type 或者直接用type定义自定义类型,

区别:

create type 变量 as table of 类型

--

create type 变量 as object(

字段1 类型1,

字段2 类型2

);

--------------------------

与 type 变量 is table of 类型

--

type 变量 is record(

字段1 类型1,

字段2 类型2

);

区别是 用 create 后面用 as , 若直接用 type 后面用is

create 是创 object , 而 type 是创record .

另 type用在语句块中,而create 是的独立的.

 

一般定义object的语法:

用

create type 自定义表类型A as table of 自定义Object类型A

和

create type 自定义Object类型A as object(

字段1 类型1,

字段2 类型2

);

与

type 自定义表类型B is table of 类型

和

type 自定义Object类型B is record(

字段1 类型1,

字段2 类型2); 

自定义类型一般分为两中,object类型和table类型.object类似于一个recored,可以表示一个表的一行数据,object的字段就相当与表的字段.自定义的table类型需要用的已经定义好的object类型.


三:type record用法概述

type 自定义Object类型B is record(

字段1 类型1,

字段2 类型2);

3.1:什么是记录(Record)?
由单行多列的标量构成的复合结构。可以看做是一种用户自定义数据类型。组成类似于多维数组。
将一个或多个标量封装成一个对象进行操作。是一种临时复合对象类型。

记录可以直接赋值。RECORD1 :=RECORD2;
记录不可以整体比较.
记录不可以整体判断为空。

3.2:%ROWTYPE和记录(Record)?
请区别%ROWTYPE和记录(Record)类型。%ROWTYPE可以说是Record的升级简化版。
区别在与前者结构为表结构,后者为自定义结构。二者在使用上没有很大区别。前者方便,后者灵活。在实际中根据情况来具体决定使用。
Record + PL/SQL表可以进行数据的多行多列存储。

3.3:如何创建和使用记录?

 ①创建记录类型
 语法:

  1. TYPE  记录名  IS RECORD  
  2.  (  
  3.   filed1 type1 [NOT NULL] [:=eXPr1],  
  4.  ....... ,  
  5.  filedN typen [NOT NULL] [:=exprn]  
  6.  )  

其中,filed1是标量的名字。
 ②声明记录类型变量:
  记录类型变量名 记录类型
 ③填充记录。
 ④访问记录成员
  记录类型变量名.filed1
  .........
  记录类型变量名.filedN
 注意:
 表字段类型修改后,还需要修改记录字段类型,有时候可能会忘记,从而出现错误。对于记录内每个字段(filed1...),可以指定也可以使用%TYPE和%ROWTYPE动态指定记录字段类型。 好处是表字段发生变化,记录字段自动改变。但是,由于每次执行前,遇到%TYPR或%ROWTYPE,数据库系统都会去查看对应表字段类型,会造成一定的数据库开销,如果系统中大量使用记录类型,则对性能会有一定影响。另外如果删除了某一字段,而自定义记录中使用了该字段,也会有可能忘记删除该字段。对数据库负荷偏低的系统,性能问题一般可以不重点关注,但是对于高负荷数据库服务器,各个环节都要考虑性能问题,每处节省一点出来,性能整体就有很大提高。

 语法:

  1. TYPE  记录名  IS RECORD  
  2. (  
  3.  filed1 table.Filed%Type [NOT NULL] [:=eXPr1] ,  
  4.  filed2 table.Filed%Type [NOT NULL] [:=eXPr1] ,  
  5.  ....... ,  
  6.  filedn table.Filed%Type [NOT NULL] [:=exprn]  
  7. );  

例子:记录可以整体赋值

  1. /*conn scott/tiger 
  2.  Create Table  empa  As  Select * From emp; 
  3.  */  
  4.  Declare  
  5.      Type EmpType is Record(  
  6.         EMPNO number(4),  
  7.         ENAME  varchar2(10),  
  8.         JOB varchar2(15),  
  9.         SAL number(7,2),  
  10.         DEPTNO number(2)  
  11.      );  
  12.    EmpRec1  EmpType;  
  13.    EmpRec2  EmpType;  
  14.  Begin  
  15.    EmpRec1.Empno:=7369;  
  16.    EmpRec1.Ename:='SMITH';  
  17.    EmpRec1.Job:='CLERK';  
  18.    EmpRec1.Sal:=800;  
  19.    EmpRec1.Deptno:=10;  
  20.    EmpRec2 := EmpRec1;  
  21.    DBMS_output.put_line(EmpRec2.empno);  
  22.  End;  
例子:记录不可以整体比较,只可以比较记录字段
  1. Declare  
  2.    Type EmpType is Record(  
  3.         EMPNO number(4),  
  4.         ENAME  varchar2(10),  
  5.         JOB varchar2(15),  
  6.         SAL number(7,2),  
  7.         DEPTNO number(2)  
  8.      );  
  9.    EmpRec1  EmpType;  
  10.    EmpRec2  EmpType;  
  11.  Begin  
  12.    EmpRec1.Empno:=7369;  
  13.    EmpRec1.Ename:='SMITH';  
  14.    EmpRec1.Job:='CLERK';  
  15.    EmpRec1.Sal:=800;  
  16.    EmpRec1.Deptno:=10;  
  17.    if EmpRec1.sal < EmpRec2.sal then  
  18.      DBMS_output.put_line('Xiao Xiao Xiao');  
  19.    end if;  
  20.  End;  

例子:记录不可以整体判断为空,只可以判断记录字段。

  1. Declare  
  2.      Type EmpType is Record(  
  3.         EMPNO number(4),  
  4.         ENAME  varchar2(10),  
  5.         JOB varchar2(15),  
  6.         SAL number(7,2),  
  7.         DEPTNO number(2)  
  8.      );  
  9.    EmpRec  EmpType;  
  10.  Begin  
  11.    if EmpRec.ename is null then  
  12.      DBMS_output.put_line('Kong Kong Kong');  
  13.    end if;  
  14.  End;  

例子:使用%TYPE和%ROWTYPE动态指定记录字段。

  1. /*conn scott/tiger 
  2. Create Table  empa  As  Select * From emp; 
  3. */  
  4. DECLARE  
  5.  Type MyRecType Is  Record  
  6.  (  
  7.   RENO   EMPA.EMPNO%Type,  
  8.   RENAME EMPA.ENAME%Type,  
  9.   RJOB   EMPA.JOB%Type  
  10.  );  
  11.  EmpRec  MyRecType;  
  12. Begin  
  13.  Select   EMPNO, ENAME, JOB  InTo  EmpRec  From empa Where empa.EMPNO = '7369';  
  14.  If  EmpRec.RJOB  = 'CLERK'  Then  
  15.   DBMS_OUTPUT.PUT_LINE('Name: '||EmpRec.RENAME);  
  16.  End If;  
  17. End;  

例子:数据集中的记录和记录类型中的数据关系。

  1. DECLARE  
  2.   Type MyRecType Is  Record  
  3.   (  
  4.    RENO   EMPA.EMPNO%Type,  
  5.    RENAME EMPA.ENAME%Type,  
  6.    RJOB   EMPA.JOB%Type  
  7.   );  
  8.   EmpRec MyRecType;  
  9.   vJob   EMPA.JOB%Type;  
  10.  Begin  
  11.   Select   EMPNO, ENAME, JOB  InTo  EmpRec  From empa Where empa.EMPNO = '7369';  
  12.   DBMS_OUTPUT.PUT_LINE('MyRecType.RJOB: '||EmpRec.RJOB);  
  13.   EmpRec.RJOB  := '修改值后'  ;  
  14.   DBMS_OUTPUT.PUT_LINE('MyRecType.RJOB: '||EmpRec.RJOB);  
  15.   Select JOB  InTo vJob  from empa  Where empa.EMPNO = EmpRec.RENO;  
  16.   DBMS_OUTPUT.PUT_LINE('EMPA.JOB: '||vJob);  
  17.  End;  
  18.  /  

3.4:使用记录向表中插入数据?
根据表结构合理安排记录字段。比如主外键。
如果用记录(RECORD)插入数据,那么只能使用记录成员;如果用%ROWTYPE插入数据,可以直接使用%ROWTYPE。
例子:使用记录成员向表中插入数据

  1. DECLARE  
  2.  Type MyRecType Is  Record  
  3.  (  
  4.   RENO  EMPA.EMPNO%Type,  
  5.   RENAME   VARCHAR2(10),  
  6.   RJOB   EMPA.JOB%Type  
  7.  );  
  8.  EmpRec MyRecType;  
  9. Begin  
  10.  Select   EMPNO, ENAME, JOB  InTo  EmpRec  From empa Where empa.EMPNO = '7369';  
  11.  DBMS_OUTPUT.PUT_LINE(EmpRec.RENO||'  '||EmpRec.RENAME||'  '||EmpRec.RJOB);  
  12.  EmpRec.RENO  := 1001;  
  13.  EmpRec.RENAME := '杰克';  
  14.  EmpRec.RJOB  := '办事员';  
  15.  Insert InTo  empa(EMPNO,ENAME,JOB)  Values(EmpRec.RENO, EmpRec.RENAME,EmpRec.RJOB);  
  16.  Select  EMPNO, ENAME, JOB  InTo  EmpRec  From empa Where empa.EMPNO = '1001';  
  17.  DBMS_OUTPUT.PUT_LINE(EmpRec.RENO||'  '||EmpRec.RENAME||'  '||EmpRec.RJOB);  
  18. End;  

3.5:使用记录更新数据?
如果用记录(RECORD)更新数据,那么只能使用记录成员;
如果用%ROWTYPE更新数据,可以直接使用%ROWTYPE。

例子:使用%ROWTYPE向表中插入数据

  1. DECLARE  
  2.  vEmp empa%RowType;  
  3. Begin  
  4.  Select  *  InTo  vEmp  From empa Where empa.EMPNO = '7369';  
  5.  UpDate empa Set ROW = vEmp Where EMPNO = 1001;  
  6. End;  

3.6:使用记录删除数据:删除记录时,只能在delete语句的where子句中使用记录成员。


四:type  table用法

4.1:定义

type 变量 is table of 类型

TYPE orders_type IS TABLE OFall_orders%ROWTYPE;

4.2:用法

1. TYPE tabletype IS TABLE OF type INDEX BY BINARY_INTEGER;

定义:

TYPEt_charTable IS TABLE OF VARCHAR2(10) INDEX BY BINARY_INTEGER; 

引用:tableName(index);  

例子:

1.

  1. declare  
  2.     type t_table is table of varchar2(10) indexby BINARY_integer;  
  3.     MyTab   t_table;  
  4.  begin  
  5.     MyTab(1) :=  'A';  
  6.     MyTab(2) :=  'B';  
  7.     MyTab(3) :=  'C';  
  8.    DBMS_OUTPUT.PUT_LINE('First index:'||'   '|| mytab(1) ||'   ');  
  9.  end;  
  10.  --  
  11.  DECLARE  
  12.       TYPE t_StudentTable IS TABLE OF students%ROWTYPE INDEXBY BINARY_INTEGER;  
  13.       v_Students t_StudentTable;  
  14.  BEGIN  
  15.  SELECT * INTO v_Students(1100)  
  16.  FROM students  
  17.  WHERE id=1100;  
  18.       DBMS_OUTPUT.PUT_LINE( v_Students(1100).OUUSRNM);  
  19.  END;  
2.--record table综合使用
  1. /*conn scott/tiger 
  2.  Create table empa as select * from emp; 
  3. */  
  4. --例子:  
  5. Declare  
  6.  Type RecType Is Record  
  7.  (  
  8.   rno  empa.empno%type,  
  9.   rname empa.ename%type,  
  10.   rsal  empa.sal%type  
  11.  );  
  12.  Type TabType Is Table Of  RecType  Index By Binary_Integer;  
  13.  MyTab TabType;  
  14.  vN Number;  
  15. Begin  
  16.  --填充  
  17.  vN := 1;  
  18.  For varR In (Select  *  From empa Order By empno ASC)  
  19.  Loop  
  20.   MyTab(vN).rno  := varR.empno;  
  21.   MyTab(vN).rname := varR.ename;  
  22.   MyTab(vN).rsal := varR.sal;  
  23.   vN := vN + 1;  
  24.  End Loop;  
  25.  --访问  
  26.  vN := MyTab.First;  
  27.  For varR In vN..MyTab.count  
  28.  Loop  
  29.   DBMS_OUTPUT.PUT_LINE(vN ||'   '||MyTab(vN).rno||'   '||MyTab(vN).rname||'   '||MyTab(vN).rsal);  
  30.   vN := MyTab.Next(vN);  
  31.  End Loop;  
  32. End;  

注意:

Oracle中index by binary_integer的作用

如语句:type  numbers is table of number index by binary_integer;其作用是,加了”index by binary_integer ”后,numbers类型的下标就是自增长,numbers类型在插入元素时,不需要初始化,不需要每次extend增加一个空间。而如果没有这句话“index by binary_integer”,那就得要显示对初始化,且每插入一个元素到numbers类型的table中时,都需要先extend.

示例:没加“index bybinary_integer”时:

  1. declare  
  2. type numbers is table of number;  
  3. n    numbers := numbers();  
  4. begin  
  5. n.extend;  
  6. n(1) := 2;  
  7. n.extend;  
  8. n(2) := 3;  
  9. for i in1 .. n.count loop  
  10. dbms_output.put_line(n(i));  
  11. end loop;  
  12. end;  
  13. --输出:2,3  
而如果加了“index by binary_integer”,代码如下写就可以达到上面的效果
  1. declare  
  2.   type numbers is table of number index by binary_integer;  
  3.   n numbers;  
  4.   begin  
  5.   n(1) := 2;  
  6.   n(2) := 3;  
  7.   for i in1 .. n.count loop  
  8.   dbms_output.put_line(n(i));  
  9.   end loop;  
  10.   end;  

五:create type 用法

5.1:定义

概念  

 方法:是在对象类型说明中用关键字  MEMBER   声明的子程序    

 方法是作为对象类型定义组成部分的一个过程或函数    

 方法不能与对象类型或其任何属性同名    

 与数据包程序相似,大多数方法有两个部分 

  1. CREATE   [OR   REPLACE]   TYPE   <typename>   AS   OBJECT  
  2. (attribute1   datatype,  
  3.     :  
  4.  attributeN   datatype  
  5.  MEMBER   PROCEDURE  <methodname>   (parameter,mode,datatype),  
  6.  MEMBER   FUNCTION   <methodname>   (parameter,mode,datatype) RETURN datatype,  
  7.  PRAGMA   RESTRICT_REFERENCES (<methodname>,WNDS/RNDS/WNPS/RNPS)  
  8. );  

说明:PRAGMA  RESTRICT_REFERENCES指定MEMBER方法按以下模式之一   操作:

  –WNDS   (不能写入数据库状态)   不能修改数据库   

 –RNDS   (不能读出数据库状态)   不能执行查询   

 –WNPS   (不能写入数据包状态)   不能更改数据包变量的值   

 –RNPS   (不能读出数据包状态)   不能引用数据包变量的值   

 例:

  1. create   or   replace   type   FLIGHT_SCH_TYPE   as   object  
  2.       (FLIGHTNO   VARCHAR2(4)   ,   AIRBUSNO   VARCHAR2(5)   ,  
  3.        ROUTE_CODE   VARCHAR2(7)   ,   DEPRT_TIME   VARCHAR2(10)   ,  
  4.        JOURNEY_HURS   VARCHAR2(10)   ,   FLIGHT_DAY1   NUMBER(1)   ,  
  5.        FLIGHT_DAY2   NUMBER(1)   ,  
  6.        Member   function   DAYS_FN(FLIGHT_DAY1   in   number)   return   varchar2   ,  
  7.        Pragma       restrict_references(DAYS_FN   ,   WNDS))   ;  

创建对象类型方法主体

  1. CREATE   [OR   REPLACE]   TYPE   BODY   <typename>   AS MEMBER FUNCTION   <methodname>   (parameter   dataype)   RETURN  <datatype>   IS<PL/SQL_block>;  
  2. MEMBER   PROCEDURE   <methodname> (parameter   datatype);  
  3. END;  

 例:

  1. create   or   replace   type   body   FLIGHT_SCH_TYPE   as  
  2.        member   function   DAYS_FN(FLIGHT_DAY1   in   number)   return   varchar2  
  3.        is  
  4.       disp_day   varchar2(20)   ;  
  5.       begin     
  6.      if   flight_day1   =   1   then  
  7.            disp_day   :=   'Sunday'   ;        
  8.      elsif   flight_day1   =   2   then  
  9.            disp_day   :=   'Monday'   ;         
  10.      elsif   flight_day1   =   3   then     
  11.           disp_day   :=   'Tuesday'   ;      
  12.      elsif   flight_day1   =   4   then     
  13.          disp_day   :=   'Wednesday'   ;      
  14.      elsif   flight_day1   =   5   then       
  15.          disp_day   :=   'Thursday'   ;          
  16.      elsif   flight_day1   =   6   then         
  17.          disp_day   :=   'Friday   '   ;    
  18.      elsif   flight_day1   =   7   then  
  19.          disp_day   :=   'Saturday'   ;   
  20.     end   if   ;          
  21.      return   disp_day   ;  
  22.   end;  
  23. end;  

调用对象方法基于类型创建表后,就可以在查询中调用对象方法  

 A. 创建基于对象的表语法:

create   table   <表名>   of   <对象类型>:此表具有该类型和member方法的所有属性,我们不能通过DBA   STUDIO的表数据编辑器来编辑数据。

例:

  1. create   table  FLIGHT_SCH_TAB   of   FLIGHT_SCH_TYPE  
  2. insert   into   FLIGHT_SCH_TAB     values('SL36','AB02','SAN-LOU','5','13:30',3,6);  

B.访问对象表中的MEMBER语法:

SELECT   <columnname>,  <aliasname>.<methodname(parameters)> FROM   <tablename>  <aliasname>;

例:

  1. select   flightno,route_code,f.days_fn(flight_day1) as  FLIGHTDAY from FLIGHT_SCH_TAB  f;  

 C.关系表中的字段为对象类型

create   table  FLIGHT_SCH_TABS(FLIGHT_DET   FLIGHT_SCH_TYPE   ,    FLIGHT_DESC   varchar2(20))   ;

注:插入数据,对于对象类型的字段的值,需要通过构造函数来得到。对象类型名称(成员1,..成员n)

例:

  1. insert   into   FLIGHT_SCH_TABS     values(FLIGHT_SCH_TYPE('SL36','AB02','SAN-LOU','5','13:30',3,6),'DESC1');    

 D.访问关系表中的Member方法此处的关系表:指表中有字段为对象类型

SELECT   <columnname>,  <aliasname>.<columnname>.<methodname (parameters)>FROM  <tablename>   <aliasname>;

例:

  1. select f.flight_det.FLIGHTNO,f.flight_det.ROUTE_CODE,f.flight_det.DAYS_FN(f.flight_det.FLIGHT_DAY1) FLIGHTDAY from flight_sch_tabs f;  

1.声明简单类型内容包括:A.对象类型的创建 B.基于对象的表的创建插入与访问 C.关系对象表的创建插入与访问   

2.通过value运算符访问基于类型的表select   value(<aliasname>)    From   <objecttable>   <aliasname>

例:

select   value(A)   FROM   FLIGHT_SCH_TAB A;--返回的是对象

select   *   from  FLIGHT_SCH_TAB;--返回的是单个的值 

3. REF运算符使您可以引用对象表中现有行的OID值.REF运算符将表别名作为输入,并且为行对象返回OID  

语法:select  REF(<aliasname>)   from   <objecttable>  <aliasname>

例:

  1. select   ref(a)   from   FLIGHT_SCH_TAB   a   ;注:FLIGHT_SCH_TAB   是基于对象的表    

 4.声明复合类型

CREATE   TYPE   name_type AS  OBJECT(name   VARCHAR2(20),   address   address_type);  

 5.定义对象之间的关系也是通过关键字REF,前面我们通过REF查询了基于对象的表中的对象的OID值,这里我们讲REF的另一个用途,即通过REF来定义对象之间的关系,称为引用的REF允许您创建行对象指针.它将创建对被引用对象位置的引用i该指针用于查询、更新或删除对象iREF由目标对象的OID、数据库标识符(列)和对象表构成iOID用于创建使用REF和DEREF运算符的外键列的关系

 iSQL和PL/SQL语句必须使用REF函数来处理对象引用

 可按如下步骤关联两个表

 1. 创建对象类型,下面我们会创建另一个表,这个表的一个字段的类型为此类型

create or replace type type_class as object(classid varchar2(10),classname varchar2(10))   

 2. 创建基于此类型的表

create table tbl_type_class of type_class      

3.创建具有外键列的关系表,有一个外键将引用1中定义的类型,并且该外键的值在2中已有的数据已经存在

create table tbl_student_ref(stuid  varchar2(20)   , stuname varchar2(20),age number(10),grade ref type_class scope is tbl_type_class)

 4.将数据插入到对象表中begin insert into tbl_type_class  values('gid1','gname1');

insert into tbl_type_class values('gid2','gname2');
commit;
end;

 5.将数据插入到关系对象表中,必须从上面创建的对象表中引用数据;  

insert into tbl_student_ref select 'stuid1','stuname1',20,ref(a) from tbl_type_class a where classid='gid1'

注:下面的方法是不行的!

insert  into   tbl_student_ref   values( 'stuid2','stuname2',20,select ref(a) from tbl_type_class a where classid='gid1')  

 6.服从值若要查看引用的值,则需要使用DEREF运算符i语法SELECT  DEREF(<列名>.<列名>)FROM  <表名>   <别名>;

例:

select   deref(grade)   from   tbl_student_ref

简单用法:

  1. create or replace type typ_calendar as object(  
  2.     年 varchar2(8),  
  3.     月 varchar2(8),  
  4.     星期日 varchar2(8),  
  5.     星期一 varchar2(8),  
  6.     星期二 varchar2(8),  
  7.     星期三 varchar2(8),  
  8.     星期四 varchar2(8),  
  9.     星期五 varchar2(8),  
  10.     星期六 varchar2(8),  
  11.     本月最后一日 varchar2(2)  
  12. );  
  13. --这种类型可以在表结构定义的时候使用:  
  14. create table tcalendar of typ_calendar;  
  15. --插入数据测试:  
  16. SQL> insert into tcalendar  
  17.   2  select typ_calendar('2010','05','1','2','3','4','5','6','7','31') from dual  
  18.   3  /  
  19. --注意:插入的数据需要用typ_calendar进行转换。  
  20. 1 row inserted  
  21. --查看结果  
  22. SQL> select * from tcalendar;  
  23. 年       月       星期日   星期一   星期二   星期三   星期四   星期五   星期六   本月最后一日  
  24. -------- -------- -------- -------- -------- -------- -------- -------- -------- ------------  
  25. 2010     05       1        2        3        4        5        6        7        31  

复杂用法:

一、抽象数据类型

1、创建类型

--地址类型

  1. CREATE OR REPLACE TYPE AddressType AS OBJECT  
  2. (  
  3. Country varchar2(15),  
  4. City varchar2(20),  
  5. Street varchar2(30)  
  6. );  

2、类型嵌套

--创建基于前一个类型的新的抽象数据类型:巨星类型

  1. CREATE OR REPLACE TYPE SuperStarType AS OBJECT  
  2. (  
  3. StarName varchar2(30),  
  4. Address AddressType  
  5. );  

3、基于抽象类型创建关系表

  1. CREATE TABLE SuperStar  
  2. (  
  3. StarID varchar(10),  
  4. Star SuperStarType  
  5. );  

4、基于抽象类型创建对象表

  1. CREATE TABLE SuperStarObj of SuperStarType;  

5、使用构造方法在表中插入记录

  1. INSERT INTO SuperStar VALUES(''001'',SuperStarType(''Zidane'',AddressType(''France'',''Paris'',''People Street NO.1'')));  

6、查询表中记录

  1. (1)SQL> SELECT * FROM SuperStar;  
  2. STARID  
  3. ----------  
  4. STAR(STARNAME, ADDRESS(COUNTRY, CITY, STREET))  
  5. --------------------------------------------------------------------------------  
  6. 001  
  7. SUPERSTARTYPE(''Zidane'', ADDRESSTYPE(''France'', ''Paris'', ''People Street NO.1''))  
  8. (2)  
  9. SELECT s.StarID,s.Star.StarName,s.Star.Address.Country,s.Star.Address.City,s.Star.Address.Street FROM SuperStar s  
  10. STARID STAR.STARNAME STAR.ADDRESS.CO STAR.ADDRESS.CITY STAR.ADDRESS.STREET  
  11. ---------- ------------------------------ --------------- -------------------- ---------------------  
  12. 001 Zidane France Paris People Street NO.1  

7、抽象数据类型的继承

(1)创建一个类型

  1. CREATE OR REPLACE TYPE PersonType AS OBJECT  
  2. (  
  3. PersonName varchar(10),  
  4. PersonSex varchar(2),  
  5. PersonBirth date  
  6. ) not final;  

(2)派生一个类型

  1. CREATE OR REPLACE TYPE StudentType UNDER PersonType  
  2. (  
  3. StudentNO int,  
  4. StudentScore int  
  5. );  

(3)查看数据字典

  1. SQL> DESC StudentType  
  2. StudentTypeextends SYS.PERSONTYPE  
  3. Name  
  4. ------------------------------------------------------------------------------  
  5. PERSONNAME  
  6. PERSONSEX  
  7. PERSONBIRTH  
  8. STUDENTNO  
  9. STUDENTSCORE  

(4)创建对象表

  1. CREATE TABLE student OF StudentType;  

(5)向对象表中插入数据

  1. INSERT INTO student VALUES(''Rose'',''nv'',to_date(''1983-05-02'',''yyyy-mm-dd''),1001,98);  

(6) 查询数据

  1. SQL> SELECT * FROM student;  
  2. PERSONNAME PE PERSONBIR STUDENTNO STUDENTSCORE  
  3. ---------- -- --------- ---------- ------------  
  4. Rose nv 02-MAY-83 1001 98  

二、可变数组

1、创建带有可变数组的表

(1)创建可变数组的基类型

  1. CREATE OR REPLACE TYPE MingXiType AS OBJECT  
  2. (  
  3. GoodID varchar2(20),  
  4. InCount int,  
  5. ProviderID varchar(20)  
  6. );  

(2)创建嵌套项类型的可变数组

  1. CREATE OR REPLACE TYPE arrMingXiType AS VARRAY(100) OF MingXiType;  

(3)创建一个主表

  1. CREATE TABLE InStockOrder  
  2. (  
  3. OrderID varchar(15) Not Null Primary Key,  
  4. InDate date,  
  5. OperatorID varchar(15),  
  6. MingXi arrMingXiType  
  7. );  

2、操作可变数组

(1)插入数据

  1. INSERT INTO InStockOrder  
  2. VALUES(''200710110001'',TO_DATE(''2007-10-11'',''YYYY-MM-DD''),''007'',  
  3. arrMingXiType(MingXiType(''G001'',100,''1001''),  
  4. MingXiType(''G002'',888,''1002''))  
  5. );  

(2)查询数据

  1. SQL> SELECT * FROM InStockOrder;  
  2. ORDERID INDATE OPERATORID  
  3. --------------- --------- ---------------  
  4. MINGXI(GOODID, INCOUNT, PROVIDERID)  
  5. ----------------------------------------------------------------------  
  6. 200710110001 11-OCT-07 007  
  7. ARRMINGXITYPE(MINGXITYPE(''G001'', 100, ''1001''), MINGXITYPE(''G002'', 888, ''1002'')  

(3)使用Table()函数

  1. SQL> SELECT * FROM Table(SELECT t.MingXi FROM InStockOrder t  
  2. WHERE t.OrderID=''200710110001'');  
  3. GOODID INCOUNT PROVIDERID  
  4. -------------------- ---------- --------------------  
  5. G001 100 1001  
  6. G002 888 1002  

(4)修改数据

  1. UPDATE InStockOrder  
  2. SET MingXi=arrMingXiType(MingXiType(''G001'',200,''1001''),  
  3. MingXiType(''G002'',8888,''1002''))  
  4. WHERE OrderID=''200710110001''  

注意:不能更新VARRAY中的单个元素,必须更新整个VARRAY

三、嵌套表

1、创建嵌套表

(1)创建嵌套表的基类型

  1. CREATE OR REPLACE TYPE MingXiType AS OBJECT  
  2. (  
  3. GoodID varchar2(20),  
  4. InCount int,  
  5. ProviderID varchar(20)  
  6. ) not final;  

(2)创建嵌套表类型

  1. CREATE OR REPLACE TYPE nestMingXiType AS TABLE OF MingXiType;  

(3)创建主表,其中一列是嵌套表类型

  1. CREATE TABLE InStockTable  
  2. (  
  3. OrderID varchar(15) Not Null Primary Key,  
  4. InDate date,  
  5. OperatorID varchar(15),  
  6. MingXi nestMingXiType  
  7. ) Nested Table MingXi STORE AS MingXiTable;  

2、操作嵌套表

(1)向嵌套表中插入记录

  1. INSERT INTO InStockTable  
  2. VALUES(''20071012001'',TO_DATE(''2007-10-12'',''YYYY-MM-DD''),''007'',  
  3. nestMingXiType(MingXiType(''G003'',666,''1001''),  
  4. MingXiType(''G004'',888,''1002''),  
  5. MingXiType(''G005'',8888,''1003''))  
  6. );  

(2)查询数据

  1. SQL> SELECT * FROM InStockTable;  
  2. ORDERID INDATE OPERATORID  
  3. --------------- --------- ---------------  
  4. MINGXI(GOODID, INCOUNT, PROVIDERID)  
  5. ----------------------------------------------------------------------------------------------------  
  6. 20071012001 12-OCT-07 007  
  7. NESTMINGXITYPE(MINGXITYPE(''G003'', 666, ''1001''), MINGXITYPE(''G004'', 888, ''1002''), MINGXITYPE(''G005'', 8888, ''1003'')  

(3)使用Table()函数

  1. SQL> SELECT * FROM Table(SELECT T.MingXi FROM InStockTable t  
  2. WHERE OrderID=''20071012001'')  
  3. GOODID INCOUNT PROVIDERID  
  4. -------------------- ---------- --------------------  
  5. G003 666 1001  
  6. G004 888 1002  
  7. G005 8888 1003  

(4)更新嵌套表中的数据

  1. UPDATE Table(SELECT t.MingXi FROM InStockTable t WHERE OrderID=''20071012001'') tt  
  2. SET tt.InCount=1666 WHERE tt.GoodID=''G003'';  

(5)删除表中数据

  1. DELETE Table(SELECT t.MingXi FROM InStockTable t WHERE OrderID=''20071012001'') tt  
  2. WHERE tt.GoodID=''G003''  

四、对象表

1、创建对象表

  1. CREATE TABLE ObjectTable OF MingXiType;  

2、向表中插入数据

  1. INSERT INTO ObjectTable VALUES(''G001'',500,''P005'');  
  2. INSERT INTO ObjectTable VALUES(''G002'',1000,''P008'');  

3、查询对象表中的记录

  1. --A 直接查询  
  2. SQL> SELECT * FROM ObjectTable;  
  3. GOODID INCOUNT PROVIDERID  
  4. -------------------- ---------- ---------------  
  5. G001 500 P005  
  6. G002 1000 P008  
  7. --B 用VALUE()函数查询  
  8. SQL> SELECT VALUE(O) FROM ObjectTable O;  
  9. VALUE(O)(GOODID, INCOUNT, PROVIDERID)  
  10. ------------------------------------------  
  11. MINGXITYPE(''G001'', 500, ''P005'')  
  12. MINGXITYPE(''G002'', 1000, ''P008'')  

4、查看对象标志符(OID)

  1. --A REF操作符引用行对象  
  2. SQL> SELECT REF(t) FROM ObjectTable t;  
  3. REF(T)  
  4. --------------------------------------------------------------------------------  
  5. 0000280209771F103ED34842478A9C439CDAEFEF6324B0ACF849F14BD7A8B52F4B0297D1C90040A9  
  6. 5A0000  
  7. 0000280209A2D3359E0F0C44B3AF652B944F8823F524B0ACF849F14BD7A8B52F4B0297D1C90040A9  
  8. 5A0001  
  9. --B 将OID用于创建外键  
  10. CREATE TABLE Customer  
  11. ( CustomerID varchar(10) PRIMARY KEY,  
  12. CustomerName varchar(20),  
  13. CustomerGoods REF MingXiType SCOPE IS ObjectTable,--引用MingXiType外键,关联的是OID的值  
  14. CustomerAddress varchar(20)  
  15. );  
  16. --C 向Customer表中插入数据,此表将从上面创建的对象表中引用数据  
  17. INSERT INTO Customer SELECT ''007'',''Yuanhy'',REF(O),''France''  
  18. FROM ObjectTable O  
  19. WHERE GoodID=''G001'';  
  20. --D 查询Customer表  
  21. SQL> SELECT * FROM Customer;  
  22. CUSTOMERID CUSTOMERNAME  
  23. ---------- --------------------  
  24. CUSTOMERGOODS  
  25. -----------------------------------------------------------------------------  
  26. CUSTOMERADDRESS  
  27. --------------------  
  28. 007 Yuanhy  
  29. 0000220208771F103ED34842478A9C439CDAEFEF6324B0ACF849F14BD7A8B52F4B0297D1C9  
  30. France  
  31. --E 用DEREF操作符返回对象的值  
  32. SQL> SELECT CustomerID,CustomerName,DEREF(t.CustomerGoods),CustomerAddress  
  33. 2 FROM Customer t;  
  34. CUSTOMERID CUSTOMERNAME  
  35. ---------- --------------------  
  36. DEREF(T.CUSTOMERGOODS)(GOODID, INCOUNT, PROVIDERID)  
  37. ----------------------------------------------------------------------------  
  38. CUSTOMERADDRESS  
  39. --------------------  
  40. 007 Yuanhy  
  41. MINGXITYPE(''G001'', 500, ''P005'')  
  42. France  

五、对象视图

将关系表化装成对象表

1、 创建对象视图

A 创建基于关系表父表的对象类型

  1. CREATE OR REPLACE TYPE depttype AS OBJECT  
  2. (  
  3. deptid number(10),  
  4. deptname varchar(30),  
  5. loc number(10)  
  6. );  

B 创建基于关系表的对象视图

  1. CREATE VIEW deptview OF depttype WITH OBJECT OID(deptid) AS  
  2. SELECT department_id,department_name,location_id FROM dept;  

C 查询视图

  1. SQL> SELECT * FROM deptview;  
  2. DEPTID DEPTNAME LOC  
  3. ---------- ------------------------------ ----------  
  4. 10 Administration 1700  
  5. 20 Marketing 1800  
  6. 30 Purchasing 1700  
  7. 40 Human Resources 2400  
  8. 50 Shipping 1500  
  9. 60 IT 1400  
  10. 70 Public Relations 2700  
  11. SQL> select ref(t) from deptview t;  
  12. REF(T)  
  13. ----------------------------------------------------------------------------------------------------  
  14. 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE  
  15. 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE  
  16. 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE  
  17. 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE  
  18. 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE  
  19. 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE  
  20. 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE  

2、创建引用视图(类似于关系表创建一个从表)

  1. CREATE VIEW empview AS SELECT MAKE_REF(deptview,department_id) deptOID,employee_id,  
  2. first_name,last_name FROM emp;  

查询对象视图empview

  1. SQL> SELECT * FROM empview;  
  2. DEPTOID  
  3. ----------------------------------------------------------------------------------------------------  
  4. EMPLOYEE_ID FIRST_NAME LAST_NAME  
  5. ----------- -------------------- -------------------------  
  6. 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE  
  7. 100 Steven King  
  8. 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE  
  9. 101 Neena Kochhar  
  10. 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE  
  11. 102 Lex De Haan  
  12. 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE  
  13. 103 Alexander Hunold  

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 * FROMSTUDENTS 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) RETURNreturn_type,

...

)

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

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

  1. CREATE TYPE BODY type_name AS  
  2. MEMBER FUNCTION method_name RETURN return_type {AS | IS}  
  3. variable declareations..  
  4. BEGIN  
  5. CODE..  
  6. RETURN return_value;  
  7. END;//END MEMBER FUNCTION  
  8. ...  
  9. END;//END TYPE BODY  
  10.  -- 如下所示:  
  11. --  
  12. CREATE TYPE HUMAN AS OBJECT(  
  13. NAME VARCHAR2(20),  
  14. SEX VARCHAR2(1),-- F : FEMALE M:MALE  
  15. BIRTHDAY DATE,  
  16. NOTE VARCHAR2(300),  
  17. MEMBER FUNCTION GET_AGE RETURN NUMBER  
  18. )  
  19. --BODY  
  20. CREATE TYPE BODY HUMAN AS  
  21. MEMBER FUNCTION GET_AGE RETURN NUMBER AS  
  22. V_MONTHS NUMBER;  
  23. BEGIN  
  24. SELECT FLOOR(MONTHS_BETWEEN(SYSDATE,BIRTHDAY)/12) INTO V_MONTHS FROM DUAL;  
  25. RETURN V_MONTHS;  
  26. END;  
  27. 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;

  映射方法:

  映射方法是一种不带参数,并返回标准的标量OracleSQL数据类型的方法,如NUMBER,VARCHAR2,Oracle将间接地使用这些方法执行比较运算.

  映射方法最重要的一个特点是:当在WHERE或ORDER BY等比较关系子句中使用对象时,会间接地使用映射方法.

  映射方法的声明只过是在普通方法声明的前面加一个MAP而以,注意:映射方法是一种不带参数的方法.

MAP MEMBER FUNCTION function_name RETURNreturn_type

  修改前文提到的HUMAN类型:

--映射方法 MAP

  1. CREATE TYPEHUMAN AS OBJECT(  
  2. NAME VARCHAR2(20),  
  3. SEX VARCHAR2(1),--F : FEMALE M:MALE  
  4. BIRTHDAY DATE,--注册日期   
  5. REGISTERDAY DATE,  
  6. NOTEVARCHAR2(300),  
  7. MEMBER FUNCTION GET_AGE RETURN NUMBER,  
  8. MAPMEMBER FUNCTION GET_GRADE RETURN NUMBER  
  9. )  
  10. CREATE TYPEBODY HUMAN AS  
  11. -----------------------  
  12. MEMBER FUNCTION GET_AGE RETURN NUMBER AS  
  13. V_MONTHS NUMBER;  
  14. BEGIN  
  15. SELECT FLOOR(MONTHS_BETWEEN(SYSDATE,BIRTHDAY)/12) INTO V_MONTHS FROM DUAL;  
  16. RETURN V_MONTHS;  
  17. END;  
  18. ------------------------  
  19. MAPMEMBER FUNCTION GET_GRADE RETURN NUMBER AS  
  20. BEGIN  
  21. RETURN MONTHS_BETWEEN(SYSDATE,BIRTHDAY);  
  22. END;  
  23. END;  

插入数据:

  1. INSERT INTO STUDENTS (STUDENT) VALUES (HUMAN(''xling'',''M'',TO_DATE(''19830714'',''YYYYMMDD''),TO_DATE(''20020915'',''YYYYMMDD''),'' 测试MAP方法''));  
  2. INSERT INTO STUDENTS (STUDENT) VALUES (HUMAN(''fairy'',''M'',TO_DATE(''19830714'',''YYYYMMDD''),TO_DATE(''20010915'',''YYYYMMDD''),'' 测试MAP方法''));  
  3. 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方法的结果为条件,可以如下:

  1. SELECT S.STUDENT.NAME,S.STUDENT.GET_GRADE() FROM STUDENTS S WHERE S.STUDENT.GET_GRADE() > 50  
  2. 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

  1. CREATE TYPE HUMAN AS OBJECT(  
  2. NAME VARCHAR2(20),  
  3. SEX VARCHAR2(1),-- F : FEMALE M:MALE  
  4. BIRTHDAY DATE,  
  5. REGISTERDAY DATE,  
  6. NOTE VARCHAR2(300),  
  7. MEMBER FUNCTION GET_AGE RETURN NUMBER,  
  8. ORDER MEMBER FUNCTION MATCH(I_STUDENT IN HUMAN) RETURN NUMBER  
  9. )  
  10. CREATE TYPE BODY HUMAN AS  
  11. -----------------------  
  12. MEMBER FUNCTION GET_AGE RETURN NUMBER AS  
  13. V_MONTHS NUMBER;  
  14. BEGIN  
  15. SELECT FLOOR(MONTHS_BETWEEN(SYSDATE,BIRTHDAY)/12) INTO V_MONTHS FROM DUAL;  
  16. RETURN V_MONTHS;  
  17. END;  
  18. ------------------------  
  19. ORDER MEMBER FUNCTION MATCH(I_STUDENT IN HUMAN) RETURN NUMBER AS  
  20. BEGIN  
  21. RETURN REGISTERDAY - I_STUDENT.REGISTERDAY;  
  22. END;  
  23. END;  

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

  1. SET SERVEROUTPUT ON  
  2. DECLARE  
  3. S1 HUMAN;  
  4. S2 HUMAN;  
  5. BEGIN  
  6.   
  7. S1 := HUMAN(''xling'',NULL,NULL,TO_DATE(''20020915'',''YYYYMMDD''),NULL);  
  8. S2 := HUMAN(''snow'',NULL,NULL,TO_DATE(''20010915'',''YYYYMMDD''),NULL);  
  9.   
  10. IF S1 > S2 THEN  
  11. DBMS_OUTPUT.PUT_LINE(S1.NAME);  
  12. ELSIF S1 < S2 THEN  
  13. DBMS_OUTPUT.PUT_LINE(S2.NAME);  
  14. ELSE  
  15. DBMS_OUTPUT.PUT_LINE(''EQUAL'');  
  16. END IF;  
  17. END;  

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

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

实例: 

(1)定义对象类型:TYPE sales_country_t

CREATE TYPE sales_country_t AS OBJECT (

  YEAR             VARCHAR2 (4),

  country          CHAR (2),

  sum_amount_sold   NUMBER

); 

(2)定义表类型:TYPE SUM_SALES_COUNTRY_T_TAB

CREATE TYPE sum_sales_country_t_tab AS TABLEOF sales_country_t;

 (3)定义对象类型:TYPE sales_gender_t

CREATE TYPE sales_gender_t AS OBJECT (

  YEAR             VARCHAR2 (4),

  country_id       CHAR (2),

  cust_gender       CHAR(1),

  sum_amount_sold   NUMBER

); 

(4)定义表类型:TYPE SUM_SALES_GENDER_T_TAB

CREATE TYPE sum_sales_gender_t_tab AS TABLEOF sales_gender_t;

 (5) 也可以使用基本类型定义  表类型比如:

create or replace typetest_tab_type as table of varchar2(4000);

varchar2(4000) 是一个资本类型,这样相当于定义的表中只有一个字段varchar2(4000)

用法:

  1. TYPE sales_country_t_rec IS RECORD (  
  2.       YEAR              VARCHAR (4),  
  3.       country           CHAR (2),  
  4.       sum_amount_sold   NUMBER  
  5.    );  
  6. v_sales_country_t_rec sales_country_t_rec;  

引用:

  1. v_sales_country_t_rec.year := 'ssss';  
  2. v_sales_country_t_rec.country := 'a';  
  3. v_sales_country_t_rec.sum_amount_sold := 2 ;  

1 首先创建一个数据类型

create type t_air  as object(id int,name varchar(20));

2 创建表

create table aaa(id int ,persont_air);

3 插入数据

insert into aaa values(1,t_air(1,'23sdf'));

4 查询classPlace

select a.id ,a.persion.id,a.person.name fromaaa a; 

t_air(1,'23sdf') 使用这个方式创建一个自定义类型t_air的对象. 

------------------------------------------------------------

三:下面简单的枚举下常用的几种自定义类型。 

1、子类型。
这种类型最简单,类似类型的一个别名,主要是为了对常用的一些类型简单化,它基于原始的某个类型。如:
有些应用会经常用到一些货币类型:number(16,2)。如果在全局范围各自定义这种类型,一旦需要修改该类型的精度,则需要一个个地修改。

那如何实现定义的全局化呢?于是就引出了子类型:

subtype cc_num is number(16,2);

这样就很方便地解决了上述的麻烦。

 

整理:

http://blog.youkuaiyun.com/qfs_v/article/details/2446941

http://blog.youkuaiyun.com/feimashenhua/article/details/7177948

http://blog.itpub.net/12932950/viewspace-662514 

http://psoug.org/reference/type.html

oracle 自定义数据类型 介绍oracle数据库自定义数据类型 oracle中有基本的数据类型,如number,varchar2,date,numeric,float…但有时候我们需要特殊的格式,如将name定义为(firstname,lastname)的形式,我们想把这个作为一个表的一列看待,这时候就要我们自己定义一个数据类型。 自定义类型分为记录数据类型(Record)和记录表类型(Table)。 其中记录数据类型Record存储是一条记录,记录表类型Table用来存储多条记录。如果记录数据类型Record是一维数组的话, 阅读详情

相关推荐

ThingsBoard PE专业版解决方案技术文档——温度&湿度

温湿度解决方案

weixin_67440240的博客 818

Oracle中你所疑惑的 Integer和Number

ORACLE中: NUMBER(10)表示长度是10, INTEGER类型表示的NUMBER长度是53 NUMBER属于ORACLE内置数据类型 PLSQL也是兼容的 NUMBER ( PRECISION, SCALE) PRECISION表示数字中的有效位。INTEGER是NUMBER的子类型,它等同于NUMBER(38,0),用来存储整数。ORACLE的数字类型有如下几种: 1.NUMBER类型 NUMBER(P,S)是最常见的数字类型,可以存放数据范围为10^130~10^126 P是长度。

长安诗社社长@-梁瀚文- https://github.com/HevnChin https://gitee.com/HevnChin 5207

VI4302 1D dToF Sensor助力无人机定高避障:一场前所未有的飞行体验

另外,传感器因测量精度不够,产生的高度信息误差,会导致无人机无法精确定高,影响飞行稳定性和安全降落。芯视界于2022年发布的全新一代基于单光子探测技术的dToF激光雷达传感器芯片-VI4302,采用单电源低功耗系统,实现高性能测距、高稳定性,同时具备极强抗阳光能力以及兼容性等强大优势。无人机可以根据传感器提供的信息,快速调整飞行路径,避开潜在的障碍物,确保平稳的飞行。VI4302 1D dToF Sensor能够以极高的精度测量物体与无人机之间的距离,实现毫米级别的测量精度。⭐ 体型小巧,灵敏度高。

致力于lidar应用开发 621

oracle中integer、pls_integer和number类型

NUMBER [ (p [, s]) ] 是ORACLE自身的数据类型。  INTEGER或者INT、SMALLINT 则是 ANSI SQL 的数据类型,它对应的ORALCE数据类型是NUMBER(38) INT、INTEGER 是 NUMBER 的受限子类型(只表示整数),相当于 NUMBER(38)。 NUMBER 类型最大可表示 38 个十进制位的数值。

variab的博客 8089

基于Python的雪球网投资组合数据爬取与分析实战:从入门到精通

在当今数字化投资时代,数据已成为投资者最重要的资产之一。雪球网作为中国领先的投资社交平台,汇聚了大量优质的投资组合数据,这些数据对于量化投资研究和个人投资决策具有重要价值。本文将详细介绍如何使用Python最新技术栈构建一个高效、稳定的雪球网投资组合爬虫,并深入分析获取的数据。投资组合持仓明细及变动历史投资收益率曲线与风险指标投资者操作策略与调仓频率热门行业与个股关注度。

2201_76125261的博客 920

《AgentScope-Java 深入浅出教程》第10章 RAG 知识检索

RAG(Retrieval-Augmented Generation,检索增强生成)是一种将信息检索与文本生成相结合的技术架构。它通过从外部知识库中检索相关文档,将检索到的信息作为上下文注入到语言模型的提示中,从而增强模型的回答质量。│ RAG 工作流程 ││ ││ 用户问题 向量检索 上下文增强 生成回答 ││ ▼ ││ │ A │ ││ ││ 1. 接收问题 ││ 2. 将问题转换为向量,在知识库中检索相似文档 ││ 3. 将检索到的文档作为上下文添加到提示词中 │。

步子哥的博客 462

oracle怎么查询自定义数据类型,oracle pl/sql中使用自定义数据类型

模式:CREATE OR REPLACE TYPE 类型名 as OBJECT (属性名 属性类型,...);举例:CREATE OR REPLACE TYPE BITS_IDX_BASE AS OBJECT ( NAME VARCHAR2(4000), FIELDS VARCHAR2(4000), CREATE_DATE VARCHAR2(4000), INCREMENT_DATE VARCHA...

weixin_29721821的博客 1272

基于通义千问2.5-7B-Instruct的技术深度解析

通义千问2.5-7B-Instruct是一个基于Transformer架构的大型语言模型,具有70亿参数。它通过自注意力机制和前馈神经网络处理输入序列,能够捕捉长距离依赖关系,适用于多种NLP任务。微调是指在预训练模型的基础上,使用特定任务的数据进行进一步训练,以使模型更好地适应特定任务。微调可以显著提高模型在特定任务上的性能。通义千问2.5-7B-Instruct是一个强大的语言模型,适用于多种NLP任务。通过深入理解其架构、微调方法和核心代码,可以更好地应用于实际场景。

zhangjiaofa的专栏 1569

Oracle 自定义数据类型Type

引言这个月项目中实现了一个动态汇总并且导出到Excel的功能,妈蛋,为了实现这个功能,一个网格页面就用了20+个存储过程和自定义函数,终于完成了初步测试工作,其中快把我所掌握的不掌握的Oracle知识都快用完了,其中有行转列(XML)、列转行、动态表、动态SQL、自定义Type、管道函数、数据流函数等,为了加深印象,便于梳理自己的知识体系,也给一些需要的人一些帮助吧,先从自定义数据类型Type开始总结。

最美不过,心中有梦,身旁有你! 6469

基于线性约束最小方差准则(LCMV)的自适应波束形成算法的matlab仿真

波束形成(BeamForming)通过对多路麦克风(常为多路全向麦)信号进行合并,抑制非目标方向信号,增强目标方向信号;进而能够实现对特定方向的聚焦拾音,能够有效提高接收信号的信噪比,也有起到降噪的作用。基本原理是波的干涉:通过调整不同阵列单元信号之间的参数,使得某些角度的信号增强,而另一些角度的信号相互抵消,例如下图中来自±45°的输入信号未被增强,而在0度方向的输入信号同相位叠加后被增强。为了将窄带波束形成扩展至宽带,可以使用频域LCMV波束形成器。

平时工作较为繁忙,私信消息一般晚上回复,谢谢大家~~ 763

AI视频生成模型训练:从数据准备到部署全流程

咱们这次的目的就像是要建造一座超级厉害的AI视频生成魔法城堡。范围呢,就是从收集建造城堡的材料(数据准备)开始,到把城堡搭建起来(模型训练),再到让城堡能供大家使用(模型部署),涵盖了整个过程的方方面面。接下来我们会先给大家介绍一些重要的术语,就像认识冒险途中的关键道具一样。然后引入一个有趣的故事,带大家进入AI视频生成的奇妙世界,解释核心概念以及它们之间的关系。接着会详细讲解核心算法原理、数学模型和公式,还会有项目实战,带大家亲自体验代码的魅力。

小白菜的博客 399

Oracle 用户自定义数据类型

用户自定义数据类型(User-defined Data Type)oracle支持对象类型(Object Type)、嵌套类型(Nested Table Type)和可变数组类型(Varray Data Type)三种用户自定义数据类型。对象类型 用于描述客观世界中存在的事物,eg 客户、订单。对象类型是在其他内置数据类型基础上建立的,可以包括多个元素(属性),这些属性共同构成了结构化的数据单元,...

weixin_30502157的博客 474

STM32F401RCT6最小系统原理图设计

STM32F401RCT6最小系统原理图设计一、主控芯片二、电源电路三、晶振电路三、下载电路四、完整电路图      本文章基于STM32F401RCT6进行最小系统原理图设计,包含主控芯片,电源,晶振电路,下载电路等几部分 一、主控芯片 主控芯片采用STM32F401RCT6,需注意: VBAT在不接电池的情况下需接3.3V,VDDAVREF+需接3.3V,否则会造成芯片供电不正常,无法启动和识别的情况 VDDAVREF+和VCAP1处电容需按照规格书

weixin_43278295的博客 2万+

[Oracle] 自定义数据类型Type

文章目录Oracle 自定义类型的种类一、TYPE type_name IS RECORD 定义记录数据类型二、TYPE table_Typename IS TABLE 定义表记录类型 Oracle 自定义类型的种类 type定义:oracle中自定义数据类型 oracle中有基本的数据类型,如number,varchar2,date,numeric,float…但有时候我们需要特殊的格式, 如将name定义为(firstname,lastname)的形式,我们想把这个作为一个表的一列看待,这时候就要我们自

涛涛之海 2377

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

oracle 赋值表数据类型,ORACLE 自定义类型 type/ object

一:Oracle中的类型有很多种,主要可以分为以下几类:1、字符串类型。如:char、nchar、varchar2、nvarchar2。2、数值类型。如:int、number(p,s)、integer、smallint。3、日期类型。如:date、interval、timestamp。4、PL/SQL类型。如:pls_integer、binary_integer、binary_double(10g...

weixin_42488997的博客 2326

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Oracle基础-自定义数据类型篇

Oracle 自定义数据类型的使用

酸菜鱼 710

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

oracle 参数类型 存储过程 获取_Oracle存储过程-自定义数据类型,集合,遍历取值

0.前言在Oracle的存储过程中,可能会遇到数据处理,假如我们目前的功能在一个Packages中Packages封装了多个不同功能的Procedure,我们在一个Procedure里面进行统计在另外一个Procedure进行计算 这就需要一个存放结果集的地方以前的解决方案是:建立了一个临时表,数据统计出来后,放入临时表中在另外一个Procedure中取出来数据,再进行计算 这样需要读写操作 浪费...

weixin_30650955的博客 627

Oracle存储过程-自定义数据类型,集合,遍历取值

0.前言        在Oracle的存储过程中,可能会遇到数据处理,假如我们目前的功能在一个Packages中     Packages封装了多个不同功能的Procedure,我们在一个Procedure里面进行统计     在另外一个Procedure进行计算 这就需要一个存放结果集的地方         以前的解决方案是:建立了一个临时表,数据统计出来后,放入临时表中     在

Hotspot 3472

Oracle如何自定义数据类型和数组和在数组中使用自定义类型

定义一个最大容量为10的person类型的VARRAY。例如,定义一个名为person的类型,它包含两个属性:name和age。关联数组:关联数组是PL/SQL中的一种数据结构,可以在运行时动态创建和使用。请注意,VARRAY的最大容量在定义时是固定的,不能在运行时更改。如果你需要动态大小的数组,应使用关联数组。VARRAY:VARRAY是PL/SQL中定义的一种静态数组类型。Oracle不直接支持数组数据类型,但你可以使用PL/SQL的关联数组或VARRAY来模拟数组。

weixin_42095178的博客 727

Hibernate自定义数据类型映射oracle中xmlType 广东精鹰软件工作室(刘正仁)

 在网上查了一些资料,竟没有Hibernate自定义数据类型映射oracle中xmlType.到国外网站上去找了一些,也不是很齐.后来折腾了一天,终于搞定了.发出来希望对网友们有点用. package com.fireeagle.common.UserType;import java.io.Serializable;import java.sql.Connection;import j

wmbb的专栏 4644

ibatis存储过程中,Oracle VARRAY自定义数据类型做IN参数的处理。

(1)在oracle中有如下自定义数据类型。 [code="sql"]create or replace type IdArray as VARRAY(255) of NUMBER; [/code](2)同时定义了一个存储过程/包。 [code="sql"]CREATE OR REPLACE PACKAGE pkg_auth IS PROCEDURE UserAdd(v_...

海风轻轻吹 282

Oracle自定义数据类型 1

原文 oracle 自定义类型 type / create type 一 Oracle中的类型 类型有很多种,主要可以分为以下几类: 1、字符串类型。如:char、nchar、varchar2、nvarchar2。2、数值类型。如:int、number(p,s)、integer、smallint。3、日期类型。如:date、interval、timestamp。4、PL/SQL类型。如:pl...

weixin_33889245的博客 179

oracle自定义的记录类型,oracle自定义数据类型

变量是用来存储值的所在处;它们有名字和数据类型。变量的数据类型决定了如何将代表这些值的位存储到计算机的内存中。在声明变量时也可指定它的数据类型。所有变量都具有数据类型,以决定能够存储哪种数据。根据缺省规定,如果在声明中没有说明数据类型,则令变量的数据类型为 Variant。Variant 数据类型很象一条变色龙— 它可在不同场合代表不同数据类型。当指定变量为 Variant 变量时,不必在数据类型...

weixin_39637059的博客 286
上一篇: 解决修改C:\Windows\System32\drivers\etc\hosts文件报错问题
下一篇: java.lang.ClassNotFoundException: weblogic.jndi.WLInitialContextFactory
CZ__
博客等级 码龄9年 97粉丝 114原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值