一: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类型.
三、创建和使用object:
1、普通类型
create or replace type typ_calendar as object(
年
varchar2(8),
月
varchar2(8),
星期日
varchar2(8),
星期一
varchar2(8),
星期二 varchar2(8),
星期三
varchar2(8),
星期四
varchar2(8),
星期五
varchar2(8),
星期六
varchar2(8),
本月最后一日
varchar2(2));
这种类型可以在表结构定义的时候使用:
create table tcalendar of typ_calendar;
插入数据测试:
insert into tcalendar
select
typ_calendar('2010','05','1','2','3','4','5','6','7','31') from
dual
注意:插入的数据需要用typ_calendar进行转换。
2、带成员函数的类型体(type body)
这种类型包含了对类型中数据的内部处理,调用该类型时,可将处理后的数据返回给调用方。
对上面的例子进行扩展。要求给当天加上特殊标识(【】)来突出显示。
首先,在typ_calendar中增加一个成员函数声明:
create or replace type typ_calendar as object(
年
varchar2(8),
月
varchar2(8),
星期日
varchar2(8),
星期一
varchar2(8),
星期二
varchar2(8),
星期三
varchar2(8),
星期四
varchar2(8),
星期五
varchar2(8),
星期六
varchar2(8),
本月最后一日
varchar2(2),
member function format(
curday
date
:= sysdate,
fmtlen pls_integer := 8
)return
typ_calendar
)
然后,创建一个type body,在type body中实现该成员函数:
create or replace type body typ_calendar as
member
function format(
curday
date
:= sysdate,
fmtlen pls_integer := 8
) return
typ_calendar as
v_return typ_calendar :=
typ_calendar('','','','','','','','','','');
v_dd
varchar2(2) := to_char(curday, 'dd');
function
fmt(
fmtstr varchar2
)return varchar2 as
begin
return lpad(fmtstr, fmtlen, ' ');
end fmt;
begin
v_return.年 := 年;
v_return.月 := 月;
v_return.星期日 := fmt(星期日);
v_return.星期一 := fmt(星期一);
v_return.星期二 := fmt(星期二);
v_return.星期三 := fmt(星期三);
v_return.星期四 := fmt(星期四);
v_return.星期五 := fmt(星期五);
v_return.星期六 := fmt(星期六);
v_return.本月最后一日 := 本月最后一日;
if (年 || lpad(月, 2, '0') = to_char(curday, 'yyyymm')) then
case v_dd
when 星期日 then
v_return.星期日 := fmt('【' || 星期日 || '】');
when 星期一 then
v_return.星期一 := fmt('【' || 星期一 || '】');
when 星期二 then
v_return.星期二 := fmt('【' || 星期二 || '】');
when 星期三 then
v_return.星期三 := fmt('【' || 星期三 || '】');
when 星期四 then
v_return.星期四 := fmt('【' || 星期四 || '】');
when 星期五 then
v_return.星期五 := fmt('【' || 星期五 || '】');
when 星期六 then
v_return.星期六 := fmt('【' || 星期六 || '】');
else null;
end case;
end if;
return v_return;
end
format;
end;
插入测试数据:
insert into
tcalendar
select
typ_calendar('2010','05','1','2','3','4','5','6','7','31') from
dual
insert into tcalendar
select
typ_calendar('2010','05','1','2','3','4','5','6','7','31').format()
from dual
insert into tcalendar
select
typ_calendar('2010','05','11','12','13','14','15','16','17','31').format()
from dual
在这里type 中的成员函数(member function)和静态函数(static function)的区别:
成员函数有隐含参数self,即自身类型,可以在执行的时候引用当前的数据并对数据进行操作。它的调用可以如下:object_expr.method()
静态函数没有该隐含参数。它的调用如下:type_name.method();
创建一个带静态函数声明的类型头
create or replace type typ_col as object(
col_name varchar2(30),
tab_name varchar2(30),
static function to_upper return typ_col
)
select typ_col.to_lower(x).tab_name,
typ_col.to_lower(x).col_name from tcol
select typ_col(column_name, table_name).to_upper().tab_name,
typ_col(column_name, table_name).to_upper().col_name
from
user_tab_columns t
where
rownum <= 10;
静态函数主要是用于处理并返回外部数据的,而成员函数是用于处理并返回内部数据的。
create or replace function show_calendar(
v_yermonth varchar2 := to_char(sysdate,
'yyyymm'))
return tbl_calendar as
v_cal
tbl_calendar;
v_seg
pls_integer := 6;
v_len
pls_integer := 8;
v_yer
varchar2(4) := substr(v_yermonth, 1, 4);
v_mon
varchar2(2) := lpad(substr(v_yermonth, 5, 2), 2, '0');
v_ini
date := to_date(v_yermonth || '01', 'yyyymmdd');
begin
select
typ_calendar(v_yer, v_mon,
case when rn >= wkn - 1 and rn - wkn + 2
<= mxdays
then rn - wkn + 2 end,
case when rn >= wkn - 2 and rn - wkn + 3
<= mxdays
then rn - wkn + 3 end,
case when rn >= wkn - 3 and rn - wkn + 4
<= mxdays
then rn - wkn + 4 end,
case when rn >= wkn - 4 and rn - wkn + 5
<= mxdays
then rn - wkn + 5 end,
case when rn >= wkn - 5 and rn - wkn + 6
<= mxdays
then rn - wkn + 6 end,
case when rn >= wkn - 6 and rn - wkn + 7
<= mxdays
then rn - wkn + 7 end,
case when rn >= wkn - 7 and rn - wkn + 8
<= mxdays
then rn - wkn + v_len end,
mxdays).format()
bulk collect into v_cal
from (select (rownum - 1)*7 rn,
to_number(to_char(trunc(v_ini, 'mm'), 'd')) wkn,
to_number(to_char(last_day(v_ini), 'dd')) mxdays
from dual
connect by rownum <= v_seg) b
where rn - wkn + 2 <= mxdays; --过滤空行
return
v_cal;
end show_calendar;
获得当前月的日历:
select * from table(show_calendar);
获取指定月份的日历:
select * from
table(show_calendar('201001'));
显示多个月的日历:
select b.*
from (select
to_char(add_months(date'1998-01-01', rownum-1), 'yyyymm') c
from dual connect by rownum <=
10)
a, table(show_calendar(to_char(a.c)))
b
自定义type的一个限制是不能使用rowid类型
特殊使用:自定义聚集函数。
with tmp as (
select '1' c from dual
union all
select '2' c from dual
union all
select '3' c from dual
union all
select '4' c from dual)
select * from tmp
1,2,3,4要合并为1->2->3->4,该如何实现?
一个办法是用层级查询来实现(用sys_connect_by_path即可)。
另外,10g下,还可以用wm_sys.wm_concat函数来实现。
还有就是自定义聚集函数了。自定义聚集函数首先要定义一个类型,在类型中调用了Oracle内部实现的几个接口函数:
CREATE OR REPLACE TYPE "TYP_STRCAT" as
object
(
strsum
varchar2(4000),
strcnt
number,
strdelimit varchar2(10),
static
function ODCIAggregateInitialize(
actx in out typ_strcat)
return
number,
member
function ODCIAggregateIterate(
self in out typ_strcat,
val in varchar2)
return
number,
member
function ODCIAggregateTerminate(
self
in typ_strcat,
returnvalue out varchar2,
flags
in number)
return
number,
member
function ODCIAggregateMerge(
self in out typ_strcat,
ctx2 typ_strcat)
return
number)
CREATE OR REPLACE TYPE BODY "TYP_STRCAT" as
static
function ODCIAggregateInitialize(actx in out typ_strcat)
return number as
begin
actx := typ_strcat(null, 1, ',');
return ODCICONST.Success;
end;
member
function ODCIAggregateIterate(self in out
typ_strcat,
val in varchar2) return number as
begin
self.strsum := self.strsum || strdelimit || val;
self.strcnt := self.strcnt + 1;
return ODCICONST.Success;
end;
member
function
ODCIAggregateTerminate(self
in typ_strcat,
returnvalue out varchar2,
flags
in number) return number as
begin
returnvalue := ltrim(self.strsum, strdelimit);
return Odciconst.Success;
end;
member
function ODCIAggregateMerge(self in out typ_strcat,
ctx2 in typ_strcat) return number as
begin
self.strsum := ctx2.strsum || self.strsum;
return Odciconst.Success;
end;
end;
然后创建函数:
CREATE OR REPLACE FUNCTION "SSUM" (p_str varchar2)return
varchar2
aggregate using typ_strcat;
然后,就可以使用字符串相加的功能了:
with tmp as (
select
'1' c from dual union all
select
'2' c from dual union all
select
'3' c from dual union all
select '4' c from dual)
select replace(ssum(c),
',', '->') from tmp
REPLACE(SSUM(C),',','->')
3、表类型
这种类型类似于一个数组类型,可以申明一维或多维。
比如说,创建一个元素长度为4000的字符串数组,则有:
create or replace type tbl_varchar2 as table of
varchar2(4000)
然后可以如下使用该类型:
select * from
table(tbl_varchar2('1','1','3','4','5','6'));
如果要获取多字段的,
select *
from table(tbl_calendar(
typ_calendar('2008','2','3','4','5','6','7','8','9','28'),
typ_calendar('2009','12','13','4','5','6','7','8','9','31'),
typ_calendar('2010','12','13','4','5','6','7','8','9','31')));
以上使用的类型都基于schema级别,如果是定义在包、函数、过程等这些结构里是不能给table函数使用的。
这种类型可以使用在管道函数中(pipelined
function)。也可以存放中间处理的数据,类似于临时表的作用,但是是存放在内存中的。
四: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]
);
例子:记录可以整体赋值
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动态指定记录字段。
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;
使用记录向表中插入数据?
根据表结构合理安排记录字段。比如主外键。
如果用记录(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;
使用记录更新数据?
如果用记录(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;
使用记录删除数据?
删除记录时,只能在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综合使用
--例子:
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
AS OBJECT
(attribute1
datatype,
:
attributeN
datatype
MEMBER
PROCEDURE
(parameter,
mode, datatype),
MEMBER
FUNCTION
(parameter,
mode, datatype)
RETURN
datatype,PRAGMA
RESTRICT_REFERENCES
(,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)
,
Memberfunction DAYS_FN(FLIGHT_DAY1
in
number)return
varchar2,
Pragma restrict_references(DAYS_FN
,
WNDS)) ;
创建对象类型方法主体
CREATE
[OR
REPLACE]
TYPE
BODY
AS MEMBER
FUNCTION
(parameter
dataype) RETURN
IS;MEMBER
PROCEDURE
(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
;
A. 创建基于对象的表语法:
create
table
of
意义:此表具有该类型和member方法的所有属性,
我们不能通过DBA
STUDIO的表数据编辑器来编辑数据。
例:create
table
FLIGHT_SCH_TAB
of FLIGHT_SCH_TYPE
insert
into
FLIGHT_SCH_TAB
values('SL36','AB02','SAN-LOU','5','13:30',3,6);
B.访问对象表中的MEMBER方法
SELECT
,
.FROM
;
例: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)
例:insert
into
FLIGHT_SCH_TABS
values(FLIGHT_SCH_TYPE('SL36','AB02','SAN-LOU','5','13:30',3,6),'DESC1');
D.访问关系表中的Member方法此处的关系表:指表中有字段为对象类型
SELECT
,
..FROM
;
例: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(
From
例:select
value(A)
FROM
FLIGHT_SCH_TAB
A
--返回的是对象区别
select
*
from
FLIGHT_SCH_TAB;--返回的是单个的值
3.
REF
运算符使您可以引用对象表中现有行的
OID
值
REF
运算符将表别名作为输入,并且为行对象返回
OID
语法:select
REF()
from
例: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 AddressType AS OBJECT
(
Country varchar2(15),
City varchar2(20),
Street varchar2(30)
);
2、类型嵌套
--创建基于前一个类型的新的抽象数据类型:巨星类型
CREATE
OR REPLACE TYPE
SuperStarType AS OBJECT
(
StarName varchar2(30),
Address AddressType
);
3、基于抽象类型创建关系表
CREATE TABLE
SuperStar
(
StarID varchar(10),
Star SuperStarType
);
4、基于抽象类型创建对象表
CREATE TABLE SuperStarObj
of SuperStarType;
5、使用构造方法在表中插入记录
INSERT INTO SuperStar
VALUES(''001'',SuperStarType(''Zidane'',AddressType(''France'',''Paris'',''People
Street
NO.1'')));
6、抽象数据类型的继承
(1)创建一个类型
CREATE OR REPLACE
TYPE PersonType AS
OBJECT
(
PersonName
varchar(10),
PersonSex varchar(2),
PersonBirth date
) not
final;
(2)派生一个类型
CREATE OR REPLACE
TYPE StudentType UNDER PersonType
(
StudentNO int,
StudentScore int
);
(3)查看数据字典
DESC StudentType
StudentType extends SYS.PERSONTYPE
(4)创建对象表
CREATE TABLE student
OF StudentType;
(5)向对象表中插入数据
INSERT INTO student
VALUES(''Rose'',''nv'',to_date(''1983-05-02'',''yyyy-mm-dd''),1001,98);
(6) 查询数据
SELECT*
FROM
student;
子类型
这种类型最简单,类似类型的一个别名,主要是为了对常用的一些类型简单化,它基于原始的某个类型。
如:
有些应用会经常用到一些货币类型:number(16,2)。如果在全局范围各自定义这种类型,一旦需要修改该类型的精度,则需要一个个地修改。
那如何实现定义的全局化呢?于是就引出了子类型: subtype cc_num is number(16,2);
这样就很方便地解决了上述的麻烦。