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类型。如: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:如何创建和使用记录?
①创建记录类型
语法:
TYPE 记录名 IS RECORD ( filed1 type1 [NOT NULL] [:=eXPr1], ....... , filedN typen [NOT NULL] [:=exprn] )
其中,filed1是标量的名字。
②声明记录类型变量:
记录类型变量名 记录类型
③填充记录。
④访问记录成员
记录类型变量名.filed1
.........
记录类型变量名.filedN
注意:
表字段类型修改后,还需要修改记录字段类型,有时候可能会忘记,从而出现错误。
对于记录内每个字段(filed1.。。。),可以指定也可以使用%TYPE和%ROWTYPE动态指定记录字段类型。
好处是表字段发生变化,记录字段自动改变。但是,由于每次执行前,遇到%TYPR或%ROWTYPE,
数据库系统都会去查看对应表字段类型,会造成一定的数据库开销,如果系统中大量使用记录类型,则对性能会有一定影响。
另外如果删除了某一字段,而自定义记录中使用了该字段,也会有可能忘记删除该字段。
对数据库负荷偏低的系统,性能问题一般可以不重点关注,但是对于高负荷数据库服务器,
各个环节都要考虑性能问题,每处节省一点出来,性能整体就有很大提高。
语法:
TYPE 记录名 IS RECORD ( filed1 table.Filed%Type [NOT NULL] [:=eXPr1] , filed2 table.Filed%Type [NOT NULL] [:=eXPr1] , ....... , filedn table.Filed%Type [NOT NULL] [:=exprn] );
例子:记录可以整体赋值
/*conn scott/tiger Create Table empa As Select * From emp; */ Declare Type EmpType is Record( EMPNO number(4), ENAME varchar2(10), JOB varchar2(15), SAL number(7,2), DEPTNO number(2) ); EmpRec1 EmpType; EmpRec2 EmpType; 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 Type EmpType is Record( EMPNO number(4), ENAME varchar2(10), JOB varchar2(15), SAL number(7,2), DEPTNO number(2) ); EmpRec1 EmpType; EmpRec2 EmpType; Begin EmpRec1.Empno:=7369; EmpRec1.Ename:='SMITH'; EmpRec1.Job:='CLERK'; EmpRec1.Sal:=800; EmpRec1.Deptno:=10; if EmpRec1.sal < EmpRec2.sal then DBMS_output.put_line('Xiao Xiao Xiao'); end if; End;
例子:记录不可以整体判断为空,只可以判断记录字段。
Declare Type EmpType is Record( EMPNO number(4), ENAME varchar2(10), JOB varchar2(15), SAL number(7,2), DEPTNO number(2) ); EmpRec EmpType; Begin if EmpRec.ename is null then DBMS_output.put_line('Kong Kong Kong'); end if; End;
例子:使用%TYPE和%ROWTYPE动态指定记录字段。
/*conn scott/tiger Create Table empa As Select * From emp; */ DECLARE Type MyRecType Is Record ( RENO EMPA.EMPNO%Type, RENAME EMPA.ENAME%Type, RJOB EMPA.JOB%Type ); EmpRec MyRecType; Begin Select EMPNO, ENAME, JOB InTo EmpRec From empa Where empa.EMPNO = '7369'; If EmpRec.RJOB = 'CLERK' Then DBMS_OUTPUT.PUT_LINE('Name: '||EmpRec.RENAME); End If; End;
例子:数据集中的记录和记录类型中的数据关系。
DECLARE Type MyRecType Is Record ( RENO EMPA.EMPNO%Type, RENAME EMPA.ENAME%Type, RJOB EMPA.JOB%Type ); EmpRec MyRecType; vJob EMPA.JOB%Type; Begin Select EMPNO, ENAME, JOB InTo EmpRec From empa Where empa.EMPNO = '7369'; DBMS_OUTPUT.PUT_LINE('MyRecType.RJOB: '||EmpRec.RJOB); EmpRec.RJOB := '修改值后' ; DBMS_OUTPUT.PUT_LINE('MyRecType.RJOB: '||EmpRec.RJOB); Select JOB InTo vJob from empa Where empa.EMPNO = EmpRec.RENO; DBMS_OUTPUT.PUT_LINE('EMPA.JOB: '||vJob); End; /
3.4:使用记录向表中插入数据?
根据表结构合理安排记录字段。比如主外键。
如果用记录(RECORD)插入数据,那么只能使用记录成员;
如果用%ROWTYPE插入数据,可以直接使用%ROWTYPE。
例子:使用记录成员向表中插入数据
DECLARE Type MyRecType Is Record ( RENO EMPA.EMPNO%Type, RENAME VARCHAR2(10), RJOB EMPA.JOB%Type ); EmpRec MyRecType; Begin Select EMPNO, ENAME, JOB InTo EmpRec From empa Where empa.EMPNO = '7369'; DBMS_OUTPUT.PUT_LINE(EmpRec.RENO||' '||EmpRec.RENAME||' '||EmpRec.RJOB); EmpRec.RENO := 1001; EmpRec.RENAME := '杰克'; EmpRec.RJOB := '办事员'; Insert InTo empa(EMPNO,ENAME,JOB) Values(EmpRec.RENO, EmpRec.RENAME,EmpRec.RJOB); Select EMPNO, ENAME, JOB InTo EmpRec From empa Where empa.EMPNO = '1001'; DBMS_OUTPUT.PUT_LINE(EmpRec.RENO||' '||EmpRec.RENAME||' '||EmpRec.RJOB); End;
3.5:使用记录更新数据?
如果用记录(RECORD)更新数据,那么只能使用记录成员;
如果用%ROWTYPE更新数据,可以直接使用%ROWTYPE。
例子:使用%ROWTYPE向表中插入数据
DECLARE vEmp empa%RowType; Begin Select * InTo vEmp From empa Where empa.EMPNO = '7369'; UpDate empa Set ROW = vEmp Where EMPNO = 1001; End;
3.6:使用记录删除数据?
删除记录时,只能在delete语句的where子句中使用记录成员。
四 type table用法
4.1:定义
type 变量 is table of 类型
TYPE orders_type IS TABLE OF all_orders%ROWTYPE;
4.2:用法
1. TYPE tabletype IS TABLE OF type INDEX BY BINARY_INTEGER;
定义:TYPE t_charTable IS TABLE OF VARCHAR2(10) INDEX BY BINARY_INTEGER;
引用:tableName(index);
例子:
declare type t_table is table of varchar2(10) indexby BINARY_integer; MyTab t_table; begin MyTab(1) := 'A'; MyTab(2) := 'B'; MyTab(3) := 'C'; DBMS_OUTPUT.PUT_LINE('First index:'||' '|| mytab(1) ||' '); end; -- DECLARE TYPE t_StudentTable IS TABLE OF students%ROWTYPE INDEXBY BINARY_INTEGER; v_Students t_StudentTable; BEGIN SELECT * INTO v_Students(1100) FROM students WHERE id=1100; DBMS_OUTPUT.PUT_LINE( v_Students(1100).OUUSRNM); END;
--record table综合使用
/*conn scott/tiger Create table empa as select * from emp; */ --例子: Declare Type RecType Is Record ( rno empa.empno%type, rname empa.ename%type, rsal empa.sal%type ); Type TabType Is Table Of RecType Index By Binary_Integer; MyTab TabType; vN Number; Begin --填充 vN := 1; For varR In (Select * From empa Order By empno ASC) Loop MyTab(vN).rno := varR.empno; MyTab(vN).rname := varR.ename; MyTab(vN).rsal := varR.sal; vN := vN + 1; End Loop; --访问 vN := MyTab.First; For varR In vN..MyTab.count Loop DBMS_OUTPUT.PUT_LINE(vN ||' '||MyTab(vN).rno||' '||MyTab(vN).rname||' '||MyTab(vN).rsal); vN := MyTab.Next(vN); End Loop; 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 by binary_integer”时:
declare type numbers is table of number; n numbers := numbers(); begin n.extend; n(1) := 2; n.extend; n(2) := 3; for i in1 .. n.count loop dbms_output.put_line(n(i)); end loop; end; --输出:2,3
而如果加了“index by binary_integer”,代码如下写就可以达到上面的效果
declare type numbers is table of number index by binary_integer; n numbers; begin n(1) := 2; n(2) := 3; for i in1 .. n.count loop dbms_output.put_line(n(i)); end loop; end;
五 create type 用法
5.1 定义
概念
方法:是在对象类型说明中用关键字 MEMBER 声明的子程序
方法是作为对象类型定义组成部分的一个过程或函数
方法不能与对象类型或其任何属性同名
与数据包程序相似,大多数方法有两个部分
CREATE [OR REPLACE] TYPE <typename> AS OBJECT (attribute1 datatype, : attributeN datatype MEMBER PROCEDURE <methodname> (parameter, mode, datatype), MEMBER FUNCTION <methodname> (parameter, mode, datatype) RETURN datatype,PRAGMA RESTRICT_REFERENCES (<methodname>,WNDS/RNDS/WNPS/RNPS) );
说明:PRAGMA RESTRICT_REFERENCES指定MEMBER方法按以下模式之一 操作:
–WNDS (不能写入数据库状态) 不能修改数据库
–RNDS (不能读出数据库状态) 不能执行查询
–WNPS (不能写入数据包状态) 不能更改数据包变量的值
–RNPS (不能读出数据包状态) 不能引用数据包变量的值
例:
create or replace type FLIGHT_SCH_TYPE as object ( FLIGHTNO VARCHAR2(4) , AIRBUSNO VARCHAR2(5) , ROUTE_CODE VARCHAR2(7) , DEPRT_TIME VARCHAR2(10) , JOURNEY_HURS VARCHAR2(10) , FLIGHT_DAY1 NUMBER(1) , FLIGHT_DAY2 NUMBER(1) , Member function DAYS_FN(FLIGHT_DAY1 in number) return varchar2 , Pragma restrict_references(DAYS_FN , WNDS) );
创建对象类型方法主体
CREATE [OR REPLACE] TYPE BODY <typename> AS MEMBER FUNCTION <methodname> (parameter dataype) RETURN <datatype> IS<PL/SQL_block>;MEMBER PROCEDURE <methodname> (parameter datatype); END;
例:
create or replace type body FLIGHT_SCH_TYPE as member function DAYS_FN(FLIGHT_DAY1 in number) return varchar2 is disp_day varchar2(20) ; begin if flight_day1 = 1 then disp_day := 'Sunday' ; elsif flight_day1 = 2 then disp_day := 'Monday' ; elsif flight_day1 = 3 then disp_day := 'Tuesday' ; elsif flight_day1 = 4 then disp_day := 'Wednesday' ; elsif flight_day1 = 5 then disp_day := 'Thursday' ; elsif flight_day1 = 6 then disp_day := 'Friday ' ; elsif flight_day1 = 7 then disp_day := 'Saturday' ; end if ; return disp_day ; end ; end ;
后续内容请参考本博客文章 Oracle自定义数据类型 2 (调用对象方法)
没有整理与归纳的知识,一文不值!高度概括与梳理的知识,才是自己真正的知识与技能。 永远不要让自己的自由、好奇、充满创造力的想法被现实的框架所束缚,让创造力自由成长吧! 多花时间,关心他(她)人,正如别人所关心你的。理想的腾飞与实现,没有别人的支持与帮助,是万万不能的。