注:为了更加清晰的看清有些没有格式的sql语句,本人修改了原文作者文章的部分sql格式
@H_301_5@
因不知原文出处,链接就不附带了...望体谅@H_301_5@
@H_301_5@
一:Oracle中的类型有很多种,主要可以分为以下几类:@H_301_5@
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。@H_301_5@
二:type / create type 区别联系@H_301_5@
相同:@H_301_5@
可用用关键字create type 或者直接用type定义自定义类型,@H_301_5@
区别:@H_301_5@
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@H_301_5@
create 是创 object,而 type 是创record .@H_301_5@
另 type用在语句块中,而create 是的独立的.@H_301_5@
@H_301_5@
一般定义object的语法:@H_301_5@
用 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类型.@H_301_5@
type 自定义Object类型B is record( 字段1 类型1,字段2 类型2);
3.1:什么是记录(Record)?
由单行多列的标量构成的复合结构。可以看做是一种用户自定义数据类型。组成类似于多维数组。
将一个或多个标量封装成一个对象进行操作。是一种临时复合对象类型。@H_301_5@
记录可以直接赋值。RECORD1 :=RECORD2;
记录不可以整体比较.
记录不可以整体判断为空。@H_301_5@
3.2:%ROWTYPE和记录(Record)?
请区别%ROWTYPE和记录(Record)类型。%ROWTYPE可以说是Record的升级简化版。
区别在与前者结构为表结构,后者为自定义结构。二者在使用上没有很大区别。前者方便,后者灵活。在实际中根据情况来具体决定使用。
Record + PL/sql表可以进行数据的多行多列存储。@H_301_5@
3.3:如何创建和使用记录?
①创建记录类型
语法:@H_301_5@
- TYPE记录名ISRECORD
- (
- filed1type1[NOTNULL][:=eXPr1],
- .......,
- filedNtypen[NOTNULL][:=exprn]
- )
其中,filed1是标量的名字。
②声明记录类型变量:
记录类型变量名 记录类型
③填充记录。
④访问记录成员
记录类型变量名.filed1
.........
记录类型变量名.filedN
注意:
表字段类型修改后,还需要修改记录字段类型,有时候可能会忘记,从而出现错误。对于记录内每个字段(filed1...),可以指定也可以使用%TYPE和%ROWTYPE动态指定记录字段类型。好处是表字段发生变化,记录字段自动改变。但是,由于每次执行前,遇到%TYPR或%ROWTYPE,数据库系统都会去查看对应表字段类型,会造成一定的数据库开销,如果系统中大量使用记录类型,则对性能会有一定影响。另外如果删除了某一字段,而自定义记录中使用了该字段,也会有可能忘记删除该字段。对数据库负荷偏低的系统,性能问题一般可以不重点关注,但是对于高负荷数据库服务器,各个环节都要考虑性能问题,每处节省一点出来,性能整体就有很大提高。@H_301_5@
语法:@H_301_5@
- TYPE记录名ISRECORD
- (
- filed1table.Filed%Type[NOTNULL][:=eXPr1],
- filed2table.Filed%Type[NOTNULL][:=eXPr1],
- .......,
- filedntable.Filed%Type[NOTNULL][:=exprn]
- );
例子:记录可以整体赋值@H_301_5@
- /*connscott/tiger
- CreateTableempaAsSelect*Fromemp;
- */
- Declare
- TypeEmpTypeisRecord(
- EMPNOnumber(4),
- ENAMEvarchar2(10),
- JOBvarchar2(15),
- SALnumber(7,2),
- DEPTNOnumber(2)
- );
- EmpRec1EmpType;
- EmpRec2EmpType;
- Begin
- EmpRec1.Empno:=7369;
- EmpRec1.Ename:='SMITH';
- EmpRec1.Job:='CLERK';
- EmpRec1.Sal:=800;
- EmpRec1.Deptno:=10;
- EmpRec2:=EmpRec1;
- DBMS_output.put_line(EmpRec2.empno);
- End;
- Declare
- TypeEmpTypeisRecord(
- EMPNOnumber(4),
- ENAMEvarchar2(10),
- JOBvarchar2(15),
- SALnumber(7,
- DEPTNOnumber(2)
- );
- EmpRec1EmpType;
- EmpRec2EmpType;
- Begin
- EmpRec1.Empno:=7369;
- EmpRec1.Ename:='SMITH';
- EmpRec1.Job:='CLERK';
- EmpRec1.Sal:=800;
- EmpRec1.Deptno:=10;
- ifEmpRec1.sal<EmpRec2.salthen
- DBMS_output.put_line('XiaoXiaoXiao');
- endif;
- End;
- Declare
- TypeEmpTypeisRecord(
- EMPNOnumber(4),
- DEPTNOnumber(2)
- );
- EmpRecEmpType;
- Begin
- ifEmpRec.enameisnullthen
- DBMS_output.put_line('KongKongKong');
- endif;
- End;
- /*connscott/tiger
- CreateTableempaAsSelect*Fromemp;
- */
- DECLARE
- TypeMyRecTypeIsRecord
- (
- RENOEMPA.EMPNO%Type,
- RENAMEEMPA.ENAME%Type,
- RJOBEMPA.JOB%Type
- );
- EmpRecMyRecType;
- Begin
- SelectEMPNO,ENAME,JOBInToEmpRecFromempaWhereempa.EMPNO='7369';
- IfEmpRec.RJOB='CLERK'Then
- DBMS_OUTPUT.PUT_LINE('Name:'||EmpRec.RENAME);
- EndIf;
- End;
- DECLARE
- TypeMyRecTypeIsRecord
- (
- RENOEMPA.EMPNO%Type,
- RENAMEEMPA.ENAME%Type,
- RJOBEMPA.JOB%Type
- );
- EmpRecMyRecType;
- vJobEMPA.JOB%Type;
- Begin
- SelectEMPNO,JOBInToEmpRecFromempaWhereempa.EMPNO='7369';
- DBMS_OUTPUT.PUT_LINE('MyRecType.RJOB:'||EmpRec.RJOB);
- EmpRec.RJOB:='修改值后';
- DBMS_OUTPUT.PUT_LINE('MyRecType.RJOB:'||EmpRec.RJOB);
- SelectJOBInTovJobfromempaWhereempa.EMPNO=EmpRec.RENO;
- DBMS_OUTPUT.PUT_LINE('EMPA.JOB:'||vJob);
- End;
- /
3.4:使用记录向表中插入数据?
根据表结构合理安排记录字段。比如主外键。
如果用记录(RECORD)插入数据,那么只能使用记录成员;如果用%ROWTYPE插入数据,可以直接使用%ROWTYPE。
例子:使用记录成员向表中插入数据@H_301_5@
- DECLARE
- TypeMyRecTypeIsRecord
- (
- RENOEMPA.EMPNO%Type,
- RENAMEVARCHAR2(10),
- RJOBEMPA.JOB%Type
- );
- EmpRecMyRecType;
- Begin
- SelectEMPNO,JOBInToEmpRecFromempaWhereempa.EMPNO='7369';
- DBMS_OUTPUT.PUT_LINE(EmpRec.RENO||''||EmpRec.RENAME||''||EmpRec.RJOB);
- EmpRec.RENO:=1001;
- EmpRec.RENAME:='杰克';
- EmpRec.RJOB:='办事员';
- InsertInToempa(EMPNO,JOB)Values(EmpRec.RENO,EmpRec.RENAME,EmpRec.RJOB);
- SelectEMPNO,JOBInToEmpRecFromempaWhereempa.EMPNO='1001';
- DBMS_OUTPUT.PUT_LINE(EmpRec.RENO||''||EmpRec.RENAME||''||EmpRec.RJOB);
- End;
3.5:使用记录更新数据?
如果用记录(RECORD)更新数据,那么只能使用记录成员;
如果用%ROWTYPE更新数据,可以直接使用%ROWTYPE。@H_301_5@
例子:使用%ROWTYPE向表中插入数据@H_301_5@
- DECLARE
- vEmpempa%RowType;
- Begin
- Select*InTovEmpFromempaWhereempa.EMPNO='7369';
- UpDateempaSetROW=vEmpWhereEMPNO=1001;
- End;
4.1:定义@H_301_5@
type 变量 is table of 类型@H_301_5@
TYPE orders_type IS TABLE OFall_orders%ROWTYPE;
1. TYPE tabletypeISTABLEOFtypeINDEXBYBINARY_INTEGER;@H_301_5@
定义:@H_301_5@
TYPEt_charTable IS TABLE OF VARCHAR2(10) INDEX BY BINARY_INTEGER;
引用:tableName(index); @H_301_5@
例子:@H_301_5@
1.@H_301_5@
- declare
- typet_tableistableofvarchar2(10)indexbyBINARY_integer;
- MyTabt_table;
- begin
- MyTab(1):='A';
- MyTab(2):='B';
- MyTab(3):='C';
- DBMS_OUTPUT.PUT_LINE('Firstindex:'||''||mytab(1)||'');
- end;
- --
- DECLARE
- TYPEt_StudentTableISTABLEOFstudents%ROWTYPEINDEXBYBINARY_INTEGER;
- v_Studentst_StudentTable;
- BEGIN
- SELECT*INTOv_Students(1100)
- FROMstudents
- WHEREid=1100;
- DBMS_OUTPUT.PUT_LINE(v_Students(1100).OUUSRNM);
- END;
- /*connscott/tiger
- Createtableempaasselect*fromemp;
- */
- --例子:
- Declare
- TypeRecTypeIsRecord
- (
- rnoempa.empno%type,
- rnameempa.ename%type,
- rsalempa.sal%type
- );
- TypeTabTypeIsTableOfRecTypeIndexByBinary_Integer;
- MyTabTabType;
- vNNumber;
- Begin
- --填充
- vN:=1;
- ForvarRIn(Select*FromempaOrderByempnoASC)
- Loop
- MyTab(vN).rno:=varR.empno;
- MyTab(vN).rname:=varR.ename;
- MyTab(vN).rsal:=varR.sal;
- vN:=vN+1;
- EndLoop;
- --访问
- vN:=MyTab.First;
- ForvarRInvN..MyTab.count
- Loop
- DBMS_OUTPUT.PUT_LINE(vN||''||MyTab(vN).rno||''||MyTab(vN).rname||''||MyTab(vN).rsal);
- vN:=MyTab.Next(vN);
- EndLoop;
- End;
注意:@H_301_5@
Oracle中index by binary_integer的作用@H_301_5@
如语句:type numbersis table of number index by binary_integer;其作用是,加了”index by binary_integer ”后,numbers类型的下标就是自增长,numbers类型在插入元素时,不需要初始化,不需要每次extend增加一个空间。而如果没有这句话“index by binary_integer”,那就得要显示对初始化,且每插入一个元素到numbers类型的table中时,都需要先extend.@H_301_5@
示例:没加“index bybinary_integer”时:@H_301_5@
- declare
- typenumbersistableofnumber;
- nnumbers:=numbers();
- begin
- n.extend;
- n(1):=2;
- n.extend;
- n(2):=3;
- foriin1..n.countloop
- dbms_output.put_line(n(i));
- endloop;
- end;
- --输出:2,3
- declare
- typenumbersistableofnumberindexbybinary_integer;
- nnumbers;
- begin
- n(1):=2;
- n(2):=3;
- foriin1..n.countloop
- dbms_output.put_line(n(i));
- endloop;
- end;
5.1:定义@H_301_5@
概念 @H_301_5@
方法:是在对象类型说明中用关键字 MEMBER 声明的子程序 @H_301_5@
方法是作为对象类型定义组成部分的一个过程或函数 @H_301_5@
- CREATE[ORREPLACE]TYPE<typename>ASOBJECT
- (attribute1datatype,
- :
- attributeNdatatype
- MEMBERPROCEDURE<methodname>(parameter,mode,datatype),
- MEMBERFUNCTION<methodname>(parameter,datatype)RETURNdatatype,
- PRAGMARESTRICT_REFERENCES(<methodname>,WNDS/RNDS/WNPS/RNPS)
- );
说明:PRAGMA RESTRICT_REFERENCES指定MEMBER方法按以下模式之一 操作:@H_301_5@
–WNDS (不能写入数据库状态) 不能修改数据库 @H_301_5@
–RNDS (不能读出数据库状态) 不能执行查询 @H_301_5@
–WNPS (不能写入数据包状态) 不能更改数据包变量的值 @H_301_5@
–RNPS (不能读出数据包状态) 不能引用数据包变量的值 @H_301_5@
例:@H_301_5@
- createorreplacetypeFLIGHT_SCH_TYPEasobject
- (FLIGHTNOVARCHAR2(4),AIRBUSNOVARCHAR2(5),
- ROUTE_CODEVARCHAR2(7),DEPRT_TIMEVARCHAR2(10),
- JOURNEY_HURSVARCHAR2(10),FLIGHT_DAY1NUMBER(1),
- FLIGHT_DAY2NUMBER(1),
- MemberfunctionDAYS_FN(FLIGHT_DAY1innumber)returnvarchar2,
- Pragmarestrict_references(DAYS_FN,WNDS));
- CREATE[ORREPLACE]TYPEBODY<typename>ASMEMBERFUNCTION<methodname>(parameterdataype)RETURN<datatype>IS<PL/sql_block>;
- MEMBERPROCEDURE<methodname>(parameterdatatype);
- END;
例:@H_301_5@
- createorreplacetypebodyFLIGHT_SCH_TYPEas
- memberfunctionDAYS_FN(FLIGHT_DAY1innumber)returnvarchar2
- is
- disp_dayvarchar2(20);
- begin
- ifflight_day1=1then
- disp_day:='Sunday';
- elsifflight_day1=2then
- disp_day:='Monday';
- elsifflight_day1=3then
- disp_day:='Tuesday';
- elsifflight_day1=4then
- disp_day:='Wednesday';
- elsifflight_day1=5then
- disp_day:='Thursday';
- elsifflight_day1=6then
- disp_day:='Friday';
- elsifflight_day1=7then
- disp_day:='Saturday';
- endif;
- returndisp_day;
- end;
- end;
调用对象方法基于类型创建表后,就可以在查询中调用对象方法 @H_301_5@
A. 创建基于对象的表语法:@H_301_5@
create table <表名> of <对象类型>:此表具有该类型和member方法的所有属性,我们不能通过DBA STUdio的表数据编辑器来编辑数据。@H_301_5@
例:
@H_301_5@
@H_301_5@
- createtableFLIGHT_SCH_TABofFLIGHT_SCH_TYPE
- insertintoFLIGHT_SCH_TABvalues('SL36','AB02','SAN-LOU','5','13:30',3,6);
B.访问对象表中的MEMBER语法:@H_301_5@
SELECT <columnname>,<aliasname>.<methodname(parameters)> FROM <tablename> <aliasname>;@H_301_5@
例:
@H_301_5@
@H_301_5@
- selectflightno,route_code,f.days_fn(flight_day1)asFLIGHTDAYfromFLIGHT_SCH_TABf;
C.关系表中的字段为对象类型@H_301_5@
create table FLIGHT_SCH_TABS(FLIGHT_DET FLIGHT_SCH_TYPE,FLIGHT_DESC varchar2(20)) ;@H_301_5@
注:插入数据,对于对象类型的字段的值,需要通过构造函数来得到。对象类型名称(成员1,..成员n)@H_301_5@例:
@H_301_5@
- insertintoFLIGHT_SCH_TABSvalues(FLIGHT_SCH_TYPE('SL36',6),'DESC1');
D.访问关系表中的Member方法此处的关系表:指表中有字段为对象类型@H_301_5@
SELECT <columnname>,<aliasname>.<columnname>.<methodname (parameters)>FROM <tablename> <aliasname>;@H_301_5@ 例:
@H_301_5@
- selectf.flight_det.FLIGHTNO,f.flight_det.ROUTE_CODE,f.flight_det.DAYS_FN(f.flight_det.FLIGHT_DAY1)FLIGHTDAYfromflight_sch_tabsf;
1.声明简单类型内容包括:A.对象类型的创建 B.基于对象的表的创建插入与访问 C.关系对象表的创建插入与访问 @H_301_5@
2.通过value运算符访问基于类型的表select value(<aliasname>) From <objecttable> <aliasname>@H_301_5@
例:@H_301_5@
select value(A) FROM FLIGHT_SCH_TAB A;--返回的是对象
@H_301_5@
select * from FLIGHT_SCH_TAB;--返回的是单个的值@H_301_5@
3. REF运算符使您可以引用对象表中现有行的OID值.REF运算符将表别名作为输入,并且为行对象返回OID @H_301_5@
@H_301_5@
语法:select REF(<aliasname>) from <objecttable> <aliasname>@H_301_5@
例:
@H_301_5@
- selectref(a)fromFLIGHT_SCH_TABa;注:FLIGHT_SCH_TAB是基于对象的表
4.声明复合类型@H_301_5@
CREATE TYPE name_type AS OBJECT(name VARCHAR2(20),address address_type); @H_301_5@
5.定义对象之间的关系也是通过关键字REF,前面我们通过REF查询了基于对象的表中的对象的OID值,这里我们讲REF的另一个用途,即通过REF来定义对象之间的关系,称为引用的REF允许您创建行对象指针.它将创建对被引用对象位置的引用i该指针用于查询、更新或删除对象iREF由目标对象的OID、数据库标识符(列)和对象表构成iOID用于创建使用REF和DEREF运算符的外键列的关系@H_301_5@
isql和PL/sql语句必须使用REF函数来处理对象引用@H_301_5@
可按如下步骤关联两个表@H_301_5@
1. 创建对象类型,下面我们会创建另一个表,这个表的一个字段的类型为此类型@H_301_5@
create or replace type type_class as object(classid varchar2(10),classname varchar2(10))
2. 创建基于此类型的表@H_301_5@
create table tbl_type_class of type_class
3.创建具有外键列的关系表,有一个外键将引用1中定义的类型,并且该外键的值在2中已有的数据已经存在@H_301_5@
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');@H_301_5@
insert into tbl_type_class values('gid2','gname2'); commit; end;
5.将数据插入到关系对象表中,必须从上面创建的对象表中引用数据; @H_301_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',select ref(a) from tbl_type_class a where classid='gid1')
6.服从值若要查看引用的值,则需要使用DEREF运算符i语法SELECT DEREF(<列名>.<列名>)FROM <表名> <别名>;@H_301_5@
例:@H_301_5@
select deref(grade) from tbl_student_ref
- createorreplacetypetyp_calendarasobject(
- 年varchar2(8),
- 月varchar2(8),
- 星期日varchar2(8),
- 星期一varchar2(8),
- 星期二varchar2(8),
- 星期三varchar2(8),
- 星期四varchar2(8),
- 星期五varchar2(8),
- 星期六varchar2(8),
- 本月最后一日varchar2(2)
- );
- --这种类型可以在表结构定义的时候使用:
- createtabletcalendaroftyp_calendar;
- --插入数据测试:
- sql>insertintotcalendar
- 2selecttyp_calendar('2010','05','1','2','3','4','6','7','31')fromdual
- 3/
- --注意:插入的数据需要用typ_calendar进行转换。
- 1rowinserted
- --查看结果
- sql>select*fromtcalendar;
- 年月星期日星期一星期二星期三星期四星期五星期六本月最后一日
- ------------------------------------------------------------------------------------
- 201005123456731
一、抽象数据类型@H_301_5@
1、创建类型@H_301_5@
--地址类型@H_301_5@
- CREATEORREPLACETYPEAddressTypeASOBJECT
- (
- Countryvarchar2(15),
- Cityvarchar2(20),
- Streetvarchar2(30)
- );
2、类型嵌套@H_301_5@
--创建基于前一个类型的新的抽象数据类型:巨星类型@H_301_5@
- CREATEORREPLACETYPESuperStarTypeASOBJECT
- (
- StarNamevarchar2(30),
- AddressAddressType
- );
3、基于抽象类型创建关系表@H_301_5@
- CREATETABLESuperStar
- (
- StarIDvarchar(10),
- StarSuperStarType
- );
4、基于抽象类型创建对象表@H_301_5@
- CREATETABLESuperStarObjofSuperStarType;
- INSERTINTOSuperStarVALUES(''001'',SuperStarType(''Zidane'',AddressType(''France'',''Paris'',''PeopleStreetNO.1'')));
- (1)sql>SELECT*FROMSuperStar;
- STARID
- ----------
- STAR(STARNAME,ADDRESS(COUNTRY,CITY,STREET))
- --------------------------------------------------------------------------------
- 001
- SUPERSTARTYPE(''Zidane'',ADDRESSTYPE(''France'',''PeopleStreetNO.1''))
- (2)
- SELECTs.StarID,s.Star.StarName,s.Star.Address.Country,s.Star.Address.City,s.Star.Address.StreetFROMSuperStars
- STARIDSTAR.STARNAMESTAR.ADDRESS.COSTAR.ADDRESS.CITYSTAR.ADDRESS.STREET
- ------------------------------------------------------------------------------------------------
- 001ZidaneFranceParisPeopleStreetNO.1
7、抽象数据类型的继承@H_301_5@
(1)创建一个类型@H_301_5@
- CREATEORREPLACETYPEPersonTypeASOBJECT
- (
- PersonNamevarchar(10),
- PersonSexvarchar(2),
- PersonBirthdate
- )notfinal;
(2)派生一个类型@H_301_5@
- CREATEORREPLACETYPEStudentTypeUNDERPersonType
- (
- StudentNOint,
- Studentscoreint
- );
(3)查看数据字典@H_301_5@
(4)创建对象表@H_301_5@
- CREATETABLEstudentOFStudentType;
(5)向对象表中插入数据@H_301_5@
- INSERTINTOstudentVALUES(''Rose'',''nv'',to_date(''1983-05-02'',''yyyy-mm-dd''),1001,98);
二、可变数组@H_301_5@
1、创建带有可变数组的表@H_301_5@
(1)创建可变数组的基类型@H_301_5@
- CREATEORREPLACETYPEMingXiTypeASOBJECT
- (
- GoodIDvarchar2(20),
- InCountint,
- ProviderIDvarchar(20)
- );
(2)创建嵌套项类型的可变数组@H_301_5@
- CREATEORREPLACETYPEarrMingXiTypeASVARRAY(100)OFMingXiType;
(3)创建一个主表@H_301_5@
- CREATETABLEInStockOrder
- (
- OrderIDvarchar(15)NotNullPrimaryKey,
- InDatedate,
- OperatorIDvarchar(15),
- MingXiarrMingXiType
- );
2、操作可变数组@H_301_5@
(1)插入数据@H_301_5@
- INSERTINTOInStockOrder
- VALUES(''200710110001'',TO_DATE(''2007-10-11'',''YYYY-MM-DD''),''007'',
- arrMingXiType(MingXiType(''G001'',100,''1001''),
- MingXiType(''G002'',888,''1002''))
- );
- sql>SELECT*FROMInStockOrder;
- ORDERIDINDATEOPERATORID
- ---------------------------------------
- MINGXI(GOODID,INCOUNT,PROVIDERID)
- ----------------------------------------------------------------------
- 20071011000111-OCT-07007
- ARRMINGXITYPE(MINGXITYPE(''G001'',MINGXITYPE(''G002'',''1002'')
- sql>SELECT*FROMTable(SELECTt.MingXiFROMInStockOrdert
- WHEREt.OrderID=''200710110001'');
- GOODIDINCOUNTPROVIDERID
- --------------------------------------------------
- G0011001001
- G0028881002
- UPDATEInStockOrder
- SETMingXi=arrMingXiType(MingXiType(''G001'',200,
- MingXiType(''G002'',8888,''1002''))
- WHEREOrderID=''200710110001''
注意:不能更新VARRAY中的单个元素,必须更新整个VARRAY@H_301_5@
三、嵌套表@H_301_5@
1、创建嵌套表@H_301_5@
(1)创建嵌套表的基类型@H_301_5@
- CREATEORREPLACETYPEMingXiTypeASOBJECT
- (
- GoodIDvarchar2(20),
- ProviderIDvarchar(20)
- )notfinal;
(2)创建嵌套表类型@H_301_5@
- CREATEORREPLACETYPEnestMingXiTypeASTABLEOFMingXiType;
(3)创建主表,其中一列是嵌套表类型@H_301_5@
- CREATETABLEInStockTable
- (
- OrderIDvarchar(15)NotNullPrimaryKey,
- MingXinestMingXiType
- )NestedTableMingXiSTOREASMingXiTable;
2、操作嵌套表@H_301_5@
(1)向嵌套表中插入记录@H_301_5@
- INSERTINTOInStockTable
- VALUES(''20071012001'',TO_DATE(''2007-10-12'',
- nestMingXiType(MingXiType(''G003'',666,
- MingXiType(''G004'',''1002''),
- MingXiType(''G005'',''1003''))
- );
- sql>SELECT*FROMInStockTable;
- ORDERIDINDATEOPERATORID
- ---------------------------------------
- MINGXI(GOODID,PROVIDERID)
- ----------------------------------------------------------------------------------------------------
- 2007101200112-OCT-07007
- NESTMINGXITYPE(MINGXITYPE(''G003'',MINGXITYPE(''G004'',MINGXITYPE(''G005'',''1003'')
- sql>SELECT*FROMTable(SELECTT.MingXiFROMInStockTablet
- WHEREOrderID=''20071012001'')
- GOODIDINCOUNTPROVIDERID
- --------------------------------------------------
- G0036661001
- G0048881002
- G00588881003
(4)更新嵌套表中的数据@H_301_5@
- UPDATETable(SELECTt.MingXiFROMInStockTabletWHEREOrderID=''20071012001'')tt
- SETtt.InCount=1666WHEREtt.GoodID=''G003'';
- DELETETable(SELECTt.MingXiFROMInStockTabletWHEREOrderID=''20071012001'')tt
- WHEREtt.GoodID=''G003''
四、对象表@H_301_5@
1、创建对象表@H_301_5@
- CREATETABLEObjectTableOFMingXiType;
2、向表中插入数据@H_301_5@
- INSERTINTOObjectTableVALUES(''G001'',500,''P005'');
- INSERTINTOObjectTableVALUES(''G002'',1000,''P008'');
- --A直接查询
- sql>SELECT*FROMObjectTable;
- GOODIDINCOUNTPROVIDERID
- ---------------------------------------------
- G001500P005
- G0021000P008
- --B用VALUE()函数查询
- sql>SELECTVALUE(O)FROMObjectTableO;
- VALUE(O)(GOODID,PROVIDERID)
- ------------------------------------------
- MINGXITYPE(''G001'',''P005'')
- MINGXITYPE(''G002'',''P008'')
4、查看对象标志符(OID)@H_301_5@
- --AREF操作符引用行对象
- sql>SELECTREF(t)FROMObjectTablet;
- REF(T)
- --------------------------------------------------------------------------------
- 0000280209771F103ED34842478A9C439CDAEFEF6324B0ACF849F14BD7A8B52F4B0297D1C90040A9
- 5A0000
- 0000280209A2D3359E0F0C44B3AF652B944F8823F524B0ACF849F14BD7A8B52F4B0297D1C90040A9
- 5A0001
- --B将OID用于创建外键
- CREATETABLECustomer
- (CustomerIDvarchar(10)PRIMARYKEY,
- CustomerNamevarchar(20),
- CustomerGoodsREFMingXiTypeSCOPEISObjectTable,--引用MingXiType外键,关联的是OID的值
- CustomerAddressvarchar(20)
- );
- --C向Customer表中插入数据,此表将从上面创建的对象表中引用数据
- INSERTINTOCustomerSELECT''007'',''Yuanhy'',REF(O),''France''
- FROMObjectTableO
- WHEREGoodID=''G001'';
- --D查询Customer表
- sql>SELECT*FROMCustomer;
- CUSTOMERIDCUSTOMERNAME
- ------------------------------
- CUSTOMERGOODS
- -----------------------------------------------------------------------------
- CUSTOMERADDRESS
- --------------------
- 007Yuanhy
- 0000220208771F103ED34842478A9C439CDAEFEF6324B0ACF849F14BD7A8B52F4B0297D1C9
- France
- --E用DEREF操作符返回对象的值
- sql>SELECTCustomerID,CustomerName,DEREF(t.CustomerGoods),CustomerAddress
- 2FROMCustomert;
- CUSTOMERIDCUSTOMERNAME
- ------------------------------
- DEREF(T.CUSTOMERGOODS)(GOODID,PROVIDERID)
- ----------------------------------------------------------------------------
- CUSTOMERADDRESS
- --------------------
- 007Yuanhy
- MINGXITYPE(''G001'',''P005'')
- France
五、对象视图@H_301_5@
将关系表化装成对象表@H_301_5@
1、 创建对象视图@H_301_5@
A 创建基于关系表父表的对象类型@H_301_5@
- CREATEORREPLACETYPEdepttypeASOBJECT
- (
- deptidnumber(10),
- deptnamevarchar(30),
- locnumber(10)
- );
B 创建基于关系表的对象视图@H_301_5@
- CREATEVIEWdeptviewOFdepttypeWITHOBJECTOID(deptid)AS
- SELECTdepartment_id,department_name,location_idFROMdept;
- sql>SELECT*FROMdeptview;
- DEPTIDDEPTNAMELOC
- --------------------------------------------------
- 10Administration1700
- 20Marketing1800
- 30Purchasing1700
- 40HumanResources2400
- 50Shipping1500
- 60IT1400
- 70PublicRelations2700
- sql>selectref(t)fromdeptviewt;
- REF(T)
- ----------------------------------------------------------------------------------------------------
- 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
- 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
- 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
- 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
- 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
- 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
- 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
2、创建引用视图(类似于关系表创建一个从表)@H_301_5@
- CREATEVIEWempviewASSELECTMAKE_REF(deptview,department_id)deptOID,employee_id,
- first_name,last_nameFROMemp;
- sql>SELECT*FROMempview;
- DEPTOID
- ----------------------------------------------------------------------------------------------------
- EMPLOYEE_IDFIRST_NAMELAST_NAME
- --------------------------------------------------------
- 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
- 100StevenKing
- 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
- 101NeenaKochhar
- 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
- 102LexDeHaan
- 00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
- 103AlexanderHunold
创建对象类型与创建表很相似,只是实际上不为存储的数据分配空间:@H_301_5@
CREATE TYPE type_name as OBJECT ( column_1 type1,column_2 type2,... );
注意:AS OBJECT创建好对象类型之后,就可以在创建表的时候,使用该类型了,如:@H_301_5@
CREATE TYPE HUMAN AS OBJECT( NAME VARCHAR2(20),SEX VARCHAR2(1),-- F : FEMALE M:MALE BIRTHDAY DATE,NOTE VARCHAR2(300) )
稍后,可以用下面的语句查看:@H_301_5@
SELECT * FROM USER_OBJECTS WHERE OBJECT_TYPE= ''TYPE'' CREATE TABLE STUDENTS( GUID NUMBER NOT NULL,STUDENTS HUMAN )
此下省去两个Trigger.插入数据的时候,可以如下:@H_301_5@
INSERT INTO STUDENTS (STUDENT) VALUES(HUMAN(''xling'',''M'',TO_DATE(''20060101'',''YYYYMMDD''),''测试''))
注意:HUMAN(''xling'',''测试''),这是个默认的构造函数.@H_301_5@
如果想选出性别为女(F)的记录,可以如下:@H_301_5@
SELECT * FROM STUDENTS S WHERE S.STUDENT.SEX= ''F''
注意:不能写成:SELECT * FROMSTUDENTS WHERE STUDENT.SEX = ''F'' 这样会报如下错误:ORA-00904:"STUDENT"."SEX": 标识符无效@H_301_5@
对象类型表:每条记录都是对象的表,称为对象类型表.它有两个使用方法:1,用作只有一个对象类型字段的表.2,用作具有对象类型字段的标准关系表.@H_301_5@
语法如下:@H_301_5@
CREATE TABLE table_name OF object_type;
例如:@H_301_5@
CREATE TABLE TMP_STUDENTS OF HUMAN;
用DESC TMP_STUDENTS,可以看到它的字段结构和HUMAN的结构一样.@H_301_5@
对象类型表有两个优点:1,从某种程度上简化了对象的使用,因为对象表的字段类型与对象类型是一致的,所以,不需要用对象名来修饰对象属性,可以把数据插入对象类型表,就像插入普通的关系表中一样:@H_301_5@
INSERT INTO TMP_STUDENTS VALUES(''xling'',TO_DATE(''20060601'',''对象类型表'');
INSERT INTO TMP_STUDENTS VALUES(HUMAN(''snow'',''F'',TO_DATE(''20060102'',''用类型的构造函数''));
第二个特点是:对象表是使用对象类型作为模板来创建表的一种便捷方式,它可以确保多个表具有相同的结构.@H_301_5@
对象类型表在:USER_TABLES表里是查不到的,而在USER_OBJECTS表里可以查到,而且OBJECT_TYPE = ''TABLE''@H_301_5@
类型在定义的时候,会自动包含一个方法,即默认的构造器.构造器的名称与对象的名称相同,它带有变量与对象类型的每个属性相对应.@H_301_5@
CREATE TYPE type_name AS OBJECT ( column1 column_type1,column2 column_type2,...,MEMBER FUNCTION method_name(args_list) RETURNreturn_type,... )
注意:是MEMBER FUNCTION,(当然,也可是MEMBER PROCEDURE,没有返回值)@H_301_5@
和包(PACKAGE)一样,如果对象类型有方法的话,还要声明一个BODY:@H_301_5@
- CREATETYPEBODYtype_nameAS
- MEMBERFUNCTIONmethod_nameRETURNreturn_type{AS|IS}
- variabledeclareations..
- BEGIN
- CODE..
- RETURNreturn_value;
- END;//ENDMEMBERFUNCTION
- ...
- END;//ENDTYPEBODY
- -- 如下所示:
- --
- CREATETYPEHUMANASOBJECT(
- NAMEVARCHAR2(20),
- SEXVARCHAR2(1),--F:FEMALEM:MALE
- BIRTHDAYDATE,
- NOTEVARCHAR2(300),
- MEMBERFUNCTIONGET_AGERETURNNUMBER
- )
- --BODY
- CREATETYPEBODYHUMANAS
- MEMBERFUNCTIONGET_AGERETURNNUMBERAS
- V_MONTHSNUMBER;
- BEGIN
- SELECTFLOOR(MONTHS_BETWEEN(SYSDATE,BIRTHDAY)/12)INTOV_MONTHSFROMDUAL;
- RETURNV_MONTHS;
- END;
- END;
注意:BODY的格式,不是AS OBJECT,也不是用小括号括起来的.MEMBER FUNCTION 后的AS或IS不能省略.@H_301_5@
还以STUDENTS表为例(注:如果类型以被某个表使用,是不能修改的,必须把相关的表删除,然后把类型删除,在一个一个新建,这里就省略了,参见前文所述)@H_301_5@
SELECT S.STUDENT.GET_AGE() FROM STUDENTS S@H_301_5@
在提起注意:表名一定要有别名.GET_AGE()的括号不能省略,否则会提示错误.@H_301_5@
下面演示在一个匿名过程中的使用情况:@H_301_5@
SET SERVEROUTPUT ON DECLARE AA HUMAN; AGE NUMBER; BEGIN AA :=HUMAN(''xingFairy'',TO_DATE(''19830714'',''过程''); AGE := AA.GET_AGE(); DBMS_OUTPUT.PUT_LINE(AGE); END;
映射方法是一种不带参数,并返回标准的标量Oraclesql数据类型的方法,如NUMBER,VARCHAR2,Oracle将间接地使用这些方法执行比较运算.@H_301_5@
映射方法最重要的一个特点是:当在WHERE或ORDER BY等比较关系子句中使用对象时,会间接地使用映射方法.@H_301_5@
映射方法的声明只过是在普通方法声明的前面加一个MAP而以,注意:映射方法是一种不带参数的方法.@H_301_5@
MAP MEMBER FUNCTION function_name RETURNreturn_type@H_301_5@
- CREATETYPEHUMANASOBJECT(
- NAMEVARCHAR2(20),
- SEXVARCHAR2(1),--F:FEMALEM:MALE
- BIRTHDAYDATE,--注册日期
- REGISTERDAYDATE,
- MEMBERFUNCTIONGET_AGERETURNNUMBER,
- MAPMEMBERFUNCTIONGET_GRADERETURNNUMBER
- )
- CREATETYPEBODYHUMANAS
- -----------------------
- MEMBERFUNCTIONGET_AGERETURNNUMBERAS
- V_MONTHSNUMBER;
- BEGIN
- SELECTFLOOR(MONTHS_BETWEEN(SYSDATE,BIRTHDAY)/12)INTOV_MONTHSFROMDUAL;
- RETURNV_MONTHS;
- END;
- ------------------------
- MAPMEMBERFUNCTIONGET_GRADERETURNNUMBERAS
- BEGIN
- RETURNMONTHS_BETWEEN(SYSDATE,BIRTHDAY);
- END;
- END;
插入数据:@H_301_5@
在执行上面的操作后,用下面这个SELECT语句可以看出映射方法的效果:@H_301_5@
SELECT S.STUDENT.NAME,S.STUDENT.GET_GRADE()FROM STUDENTS S ORDER BY STUDENT
它是按MAP方法GET_GRADE()的值进行排序的.注意是ORDER BY STUDENT,在提起一次需要注意,一定要用表的别名,方法后的括号不能省略,即使没有参数.@H_301_5@
如果想以MAP方法的结果为条件,可以如下:@H_301_5@
- SELECTS.STUDENT.NAME,S.STUDENT.GET_GRADE()FROMSTUDENTSSWHERES.STUDENT.GET_GRADE()>50
- SELECTS.STUDENT.NAME,S.STUDENT.GET_GRADE()FROMSTUDENTSSWHERESTUDENT>HUMAN(NULL,NULL,TO_DATE(''20020101'',NULL);
先说一下SELF,Oracle里对象的SELF和JAVA里的this是同一个意思.@H_301_5@
对象的排序方法具有一个与对象类型相同的参数,暂称为ARG1,用于和SELF对象进行比较.如果调用方法的SELF对象比ARG1小,返回负值,如果相等,返回0,如果SELF大于ARG1,则返回值大于0.@H_301_5@
- CREATETYPEHUMANASOBJECT(
- NAMEVARCHAR2(20),
- REGISTERDAYDATE,
- ORDERMEMBERFUNCTIONMATCH(I_STUDENTINHUMAN)RETURNNUMBER
- )
- CREATETYPEBODYHUMANAS
- -----------------------
- MEMBERFUNCTIONGET_AGERETURNNUMBERAS
- V_MONTHSNUMBER;
- BEGIN
- SELECTFLOOR(MONTHS_BETWEEN(SYSDATE,BIRTHDAY)/12)INTOV_MONTHSFROMDUAL;
- RETURNV_MONTHS;
- END;
- ------------------------
- ORDERMEMBERFUNCTIONMATCH(I_STUDENTINHUMAN)RETURNNUMBERAS
- BEGIN
- RETURNREGISTERDAY-I_STUDENT.REGISTERDAY;
- END;
- END;
注意:在声明的时候,ORDER方法的参数类型要和SELF的类型一致.@H_301_5@
- SETSERVEROUTPUTON
- DECLARE
- S1HUMAN;
- S2HUMAN;
- BEGIN
- S1:=HUMAN(''xling'',NULL);
- S2:=HUMAN(''snow'',NULL);
- IFS1>S2THEN
- DBMS_OUTPUT.PUT_LINE(S1.NAME);
- ELSIFS1<S2THEN
- DBMS_OUTPUT.PUT_LINE(S2.NAME);
- ELSE
- DBMS_OUTPUT.PUT_LINE(''EQUAL'');
- ENDIF;
- END;
注意S1 和 S2是怎么比较的.@H_301_5@
映射方法具有效率方面的优势,因为它把每个对象与单个标量值联系在一起;排序方法有灵活方面的优势,它可以在两个对象之间进行任意复杂的比较.排序方法比映射方法的速度慢.@H_301_5@
实例:@H_301_5@
(1)定义对象类型:TYPE sales_country_t@H_301_5@
CREATE TYPE sales_country_t AS OBJECT ( YEAR VARCHAR2 (4),country CHAR (2),sum_amount_sold NUMBER );
(2)定义表类型:TYPE SUM_SALES_COUNTRY_T_TAB@H_301_5@
CREATE TYPE sum_sales_country_t_tab AS TABLEOF sales_country_t;
(3)定义对象类型:TYPE sales_gender_t@H_301_5@
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@H_301_5@
CREATE TYPE sum_sales_gender_t_tab AS TABLEOF sales_gender_t;
(5) 也可以使用基本类型定义 表类型比如:@H_301_5@
create or replace typetest_tab_type as table of varchar2(4000);
varchar2(4000) 是一个资本类型,这样相当于定义的表中只有一个字段varchar2(4000)@H_301_5@
- TYPEsales_country_t_recISRECORD(
- YEARVARCHAR(4),
- countryCHAR(2),
- sum_amount_soldNUMBER
- );
- v_sales_country_t_recsales_country_t_rec;
引用:@H_301_5@
- v_sales_country_t_rec.year:='ssss';
- v_sales_country_t_rec.country:='a';
- v_sales_country_t_rec.sum_amount_sold:=2;
1 首先创建一个数据类型@H_301_5@
create type t_air as object(id int,name varchar(20));
2 创建表@H_301_5@
create table aaa(id int,persont_air);
3 插入数据@H_301_5@
insert into aaa values(1,t_air(1,'23sdf'));
select a.id,a.persion.id,a.person.name fromaaa a;
t_air(1,'23sdf') 使用这个方式创建一个自定义类型t_air的对象.@H_301_5@
------------------------------------------------------------@H_301_5@
三:下面简单的枚举下常用的几种自定义类型。@H_301_5@
1、子类型。
这种类型最简单,类似类型的一个别名,主要是为了对常用的一些类型简单化,它基于原始的某个类型。如:
有些应用会经常用到一些货币类型:number(16,2)。如果在全局范围各自定义这种类型,一旦需要修改该类型的精度,则需要一个个地修改。
@H_301_5@
@H_464_403@那如何实现定义的全局化呢?于是就引出了子类型:@H_301_5@
subtype cc_num is number(16,2);
@H_301_5@
整理:@H_301_5@
http://www.jb51.cc/article/p-bejdqwfe-bhc.html@H_301_5@
http://www.jb51.cc/article/p-yldnglfm-y.html@H_301_5@
http://blog.itpub.net/12932950/viewspace-662514@H_301_5@
http://psoug.org/reference/type.html@H_301_5@