一:Oracle中的類型有不少種,主要能夠分爲如下幾類:html
一、字符串類型。如:char、nchar、varchar二、nvarchar2。 sql
二、數值類型。如:int、number(p,s)、integer、smallint。 數據庫
三、日期類型。如:date、interval、timestamp。 數組
四、PL/SQL類型。如:pls_integer、binary_integer、binary_double(10g)、binary_float(10g)、boolean。plsql類型是不能在sql環境中使用的,好比建表時。 服務器
五、自定義類型:type / create type。oracle
二:type / create type 區別聯繫編輯器
相同:ide
可用用關鍵字create type 或者直接用type定義自定義類型,函數
區別:oop
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
2
3
4
5
6
|
TYPE 記錄名 IS RECORD
(
filed1 type1 [ NOT NULL ] [:=eXPr1],
....... ,
filedN typen [ NOT NULL ] [:=exprn]
)
|
其中,filed1是標量的名字。
②聲明記錄類型變量: 記錄類型變量名 記錄類型
③填充記錄。
④訪問記錄成員 記錄類型變量名.filed1 ......... 記錄類型變量名.filedN
注意: 表字段類型修改後,還須要修改記錄字段類型,有時候可能會忘記,從而出現錯誤。 對於記錄內每一個字段(filed1.。。。),能夠指定也可使用%TYPE和%ROWTYPE動態指定記錄字段類型。
好處是表字段發生變化,記錄字段自動改變。可是,因爲每次執行前,遇到%TYPR或%ROWTYPE, 數據庫系統都會去查看對應表字段類型,會形成必定的數據庫開銷,若是系統中大量使用記錄類型,則對性能會有必定影響。 另外若是刪除了某一字段,而自定義記錄中使用了該字段,也會有可能忘記刪除該字段。 對數據庫負荷偏低的系統,性能問題通常能夠不重點關注,可是對於高負荷數據庫服務器, 各個環節都要考慮性能問題,每處節省一點出來,性能總體就有很大提升。
語法:
1
2
3
4
5
6
7
|
TYPE 記錄名 IS RECORD
(
filed1 table .Filed%Type [ NOT NULL ] [:=eXPr1] ,
filed2 table .Filed%Type [ NOT NULL ] [:=eXPr1] ,
....... ,
filedn table .Filed%Type [ NOT NULL ] [:=exprn]
);
|
例子:記錄能夠總體賦值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
/*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 ;
|
例子:記錄不能夠總體比較,只能夠比較記錄字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
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 ;
|
例子:記錄不能夠總體判斷爲空,只能夠判斷記錄字段。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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動態指定記錄字段。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/*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 ;
|
例子:數據集中的記錄和記錄類型中的數據關係。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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。
例子:使用記錄成員向表中插入數據
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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向表中插入數據
1
2
3
4
5
6
|
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);
例子:
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
declare
type t_table is table of var char2( 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綜合使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
/*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」時:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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 ;
|
而若是加了「index by binary_integer」,代碼以下寫就能夠達到上面的效果
1
2
3
4
5
6
7
8
9
10
|
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 聲明的子程序
方法是做爲對象類型定義組成部分的一個過程或函數
方法不能與對象類型或其任何屬性同名
與數據包程序類似,大多數方法有兩個部分
1
2
3
4
5
6
7
8
9
|
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 (不能讀出數據包狀態) 不能引用數據包變量的值
例:
1
2
3
4
5
6
7
|
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)) ;
|
建立對象類型方法主體
1
2
3
4
5
|
CREATE [OR REPLACE] TYPE BODY <typename> AS MEMBER
FUNCTION <methodname> (parameter dataype) RETURN
<datatype> IS<PL/SQL_block>;MEMBER PROCEDURE <methodname>
(parameter datatype);
END;
|
例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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 <columnname>, <aliasname>.<methodname(parameters)>FROM <tablename> <aliasname>;
例: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 <columnname>, <aliasname>.<columnname>.<methodname (parameters)>FROM <tablename> <aliasname>;
例: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>
例: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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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;
SQL> insert into tcalendar
2 select typ_calendar( '2010' , '05' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '31' ) from dual
3 /
1 row inserted
SQL> select * from tcalendar;
年 月 星期日 星期一 星期二 星期三 星期四 星期五 星期六 本月最後一日
2010 05 1 2 3 4 5 6 7 31
|
複雜用法:
1、抽象數據類型
一、建立類型
--地址類型
CREATE OR REPLACE TYPE AddressType AS OBJECT
(
Country varchar2(15),
City varchar2(20),
Street varchar2(30)
);
二、類型嵌套
--建立基於前一個類型的新的抽象數據類型:巨星類型
1
2
3
4
5
|
CREATE OR REPLACE TYPE SuperStarType AS OBJECT
(
StarName varchar2(30),
Address AddressType
);
|
三、基於抽象類型建立關係表
1
2
3
4
5
|
CREATE TABLE SuperStar
(
StarID varchar (10),
Star SuperStarType
);
|
四、基於抽象類型建立對象表
1
|
CREATE TABLE SuperStarObj of SuperStarType;
|
五、使用構造方法在表中插入記錄
1
|
INSERT INTO SuperStar VALUES( '' 001 '' ,SuperStarType( '' Zidane '' ,AddressType( '' France '' , '' Paris '' , '' People Street NO. 1 '' )));
|
六、查詢表中記錄
1
2
3
4
5
6
7
8
9
10
11
12
|
(1)SQL> SELECT * FROM SuperStar;
STARID
STAR(STARNAME, ADDRESS(COUNTRY, CITY, STREET))
001
SUPERSTARTYPE( '' Zidane '' , ADDRESSTYPE( '' France '' , '' Paris '' , '' People Street NO .1 '' ))
(2)
SELECT s.StarID,s.Star.StarName,s.Star.Address.Country,s.Star.Address.City,s.Star.Address.Street FROM SuperStar s
STARID STAR.STARNAME STAR.ADDRESS.CO STAR.ADDRESS.CITY STAR.ADDRESS.STREET
001 Zidane France Paris People Street NO .1
|
七、抽象數據類型的繼承
(1)建立一個類型
1
2
3
4
5
6
|
CREATE OR REPLACE TYPE PersonType AS OBJECT
(
PersonName varchar (10),
PersonSex varchar (2),
PersonBirth date
) not final;
|
(2)派生一個類型
1
2
3
4
5
|
CREATE OR REPLACE TYPE StudentType UNDER PersonType
(
StudentNO int ,
StudentScore int
);
|
(3)查看數據字典
1
2
3
4
5
6
7
8
9
|
SQL> DESC StudentType
StudentType extends SYS.PERSONTYPE
Name
PERSONNAME
PERSONSEX
PERSONBIRTH
STUDENTNO
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
2
3
4
|
SQL> SELECT * FROM student;
PERSONNAME PE PERSONBIR STUDENTNO STUDENTSCORE
Rose nv 02-MAY-83 1001 98
|
2、可變數組
一、建立帶有可變數組的表
(1)建立可變數組的基類型
1
2
3
4
5
6
|
CREATE OR REPLACE TYPE MingXiType AS OBJECT
(
GoodID varchar2(20),
InCount int ,
ProviderID varchar (20)
);
|
(2)建立嵌套項類型的可變數組
1
|
CREATE OR REPLACE TYPE arrMingXiType AS VARRAY(100) OF MingXiType;
|
(3)建立一個主表
1
2
3
4
5
6
7
|
CREATE TABLE InStockOrder
(
OrderID varchar (15) Not Null Primary Key ,
InDate date ,
OperatorID varchar (15),
MingXi arrMingXiType
);
|
二、操做可變數組
(1)插入數據
1
2
3
4
5
|
INSERT INTO InStockOrder
VALUES ( '' 200710110001 '' ,TO_DATE( '' 2007-10-11 '' , '' YYYY-MM-DD '' ), '' 007 '' ,
arrMingXiType(MingXiType( '' G001 '' ,100, '' 1001 '' ),
MingXiType( '' G002 '' ,888, '' 1002 '' ))
);
|
(2)查詢數據
1
2
3
4
5
6
7
|
SQL> SELECT * FROM InStockOrder;
ORDERID INDATE OPERATORID
MINGXI(GOODID, INCOUNT, PROVIDERID)
200710110001 11-OCT-07 007
ARRMINGXITYPE(MINGXITYPE( '' G001 '' , 100, '' 1001 '' ), MINGXITYPE( '' G002 '' , 888, '' 1002 '' )
|
(3)使用Table()函數
1
2
3
4
5
6
|
SQL> SELECT * FROM Table ( SELECT t.MingXi FROM InStockOrder t
WHERE t.OrderID= '' 200710110001 '' );
GOODID INCOUNT PROVIDERID
G001 100 1001
G002 888 1002
|
(4)修改數據
1
2
3
4
|
UPDATE InStockOrder
SET MingXi=arrMingXiType(MingXiType( '' G001 '' ,200, '' 1001 '' ),
MingXiType( '' G002 '' ,8888, '' 1002 '' ))
WHERE OrderID= '' 200710110001 ''
|
注意:不能更新VARRAY中的單個元素,必須更新整個VARRAY
3、嵌套表
一、建立嵌套表
(1)建立嵌套表的基類型
1
2
3
4
5
6
|
CREATE OR REPLACE TYPE MingXiType AS OBJECT
(
GoodID varchar2(20),
InCount int ,
ProviderID varchar (20)
) not final;
|
(2)建立嵌套表類型
1
|
CREATE OR REPLACE TYPE nestMingXiType AS TABLE OF MingXiType;
|
(3)建立主表,其中一列是嵌套表類型
1
2
3
4
5
6
7
|
CREATE TABLE InStockTable
(
OrderID varchar (15) Not Null Primary Key ,
InDate date ,
OperatorID varchar (15),
MingXi nestMingXiType
) Nested Table MingXi STORE AS MingXiTable;
|
二、操做嵌套表
(1)向嵌套表中插入記錄
1
2
3
4
5
6
|
INSERT INTO InStockTable
VALUES ( '' 20071012001 '' ,TO_DATE( '' 2007-10-12 '' , '' YYYY-MM-DD '' ), '' 007 '' ,
nestMingXiType(MingXiType( '' G003 '' ,666, '' 1001 '' ),
MingXiType( '' G004 '' ,888, '' 1002 '' ),
MingXiType( '' G005 '' ,8888, '' 1003 '' ))
);
|
(2)查詢數據
1
2
3
4
5
6
7
|
SQL> SELECT * FROM InStockTable;
ORDERID INDATE OPERATORID
MINGXI(GOODID, INCOUNT, PROVIDERID)
20071012001 12-OCT-07 007
NESTMINGXITYPE(MINGXITYPE( '' G003 '' , 666, '' 1001 '' ), MINGXITYPE( '' G004 '' , 888, '' 1002 '' ), MINGXITYPE( '' G005 '' , 8888, '' 1003 '' )
|
(3)使用Table()函數
1
2
3
4
5
6
7
|
SQL> SELECT * FROM Table ( SELECT T.MingXi FROM InStockTable t
WHERE OrderID= '' 20071012001 '' )
GOODID INCOUNT PROVIDERID
G003 666 1001
G004 888 1002
G005 8888 1003
|
(4)更新嵌套表中的數據
1
2
|
UPDATE Table ( SELECT t.MingXi FROM InStockTable t WHERE OrderID= '' 20071012001 '' ) tt
SET tt.InCount=1666 WHERE tt.GoodID= '' G003 '' ;
|
(5)刪除表中數據
1
2
|
DELETE Table ( SELECT t.MingXi FROM InStockTable t WHERE OrderID= '' 20071012001 '' ) tt
WHERE tt.GoodID= '' G003 ''
|
4、對象表
一、建立對象表
1
|
CREATE TABLE ObjectTable OF MingXiType;
|
二、向表中插入數據
1
2
|
INSERT INTO ObjectTable VALUES ( '' G001 '' ,500, '' P005 '' );
INSERT INTO ObjectTable VALUES ( '' G002 '' ,1000, '' P008 '' );
|
三、查詢對象表中的記錄
1
2
3
4
5
6
7
8
9
10
11
12
|
SQL> SELECT * FROM ObjectTable;
GOODID INCOUNT PROVIDERID
G001 500 P005
G002 1000 P008
SQL> SELECT VALUE(O) FROM ObjectTable O;
VALUE(O)(GOODID, INCOUNT, PROVIDERID)
MINGXITYPE( '' G001 '' , 500, '' P005 '' )
MINGXITYPE( '' G002 '' , 1000, '' P008 '' )
|
四、查看對象標誌符(OID)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
SQL> SELECT REF(t) FROM ObjectTable t;
REF(T)
0000280209771F103ED34842478A9C439CDAEFEF6324B0ACF849F14BD7A8B52F4B0297D1C90040A9
5A0000
0000280209A2D3359E0F0C44B3AF652B944F8823F524B0ACF849F14BD7A8B52F4B0297D1C90040A9
5A0001
CREATE TABLE Customer
( CustomerID varchar (10) PRIMARY KEY ,
CustomerName varchar (20),
CustomerGoods REF MingXiType SCOPE IS ObjectTable,
CustomerAddress varchar (20)
);
INSERT INTO Customer SELECT '' 007 '' , '' Yuanhy '' ,REF(O), '' France ''
FROM ObjectTable O
WHERE GoodID= '' G001 '' ;
SQL> SELECT * FROM Customer;
CUSTOMERID CUSTOMERNAME
CUSTOMERGOODS
CUSTOMERADDRESS
007 Yuanhy
0000220208771F103ED34842478A9C439CDAEFEF6324B0ACF849F14BD7A8B52F4B0297D1C9
France
SQL> SELECT CustomerID,CustomerName,DEREF(t.CustomerGoods),CustomerAddress
2 FROM Customer t;
CUSTOMERID CUSTOMERNAME
DEREF(T.CUSTOMERGOODS)(GOODID, INCOUNT, PROVIDERID)
CUSTOMERADDRESS
007 Yuanhy
MINGXITYPE( '' G001 '' , 500, '' P005 '' )
France
|
5、對象視圖
將關係表化裝成對象表
一、 建立對象視圖
A 建立基於關係表父表的對象類型
1
2
3
4
5
6
|
CREATE OR REPLACE TYPE depttype AS OBJECT
(
deptid number(10),
deptname varchar (30),
loc number(10)
);
|
B 建立基於關係表的對象視圖
1
2
|
CREATE VIEW deptview OF depttype WITH OBJECT OID(deptid) AS
SELECT department_id,department_name,location_id FROM dept;
|
C 查詢視圖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
SQL> SELECT * FROM deptview;
DEPTID DEPTNAME LOC
10 Administration 1700
20 Marketing 1800
30 Purchasing 1700
40 Human Resources 2400
50 Shipping 1500
60 IT 1400
70 Public Relations 2700
SQL> select ref(t) from deptview t;
REF(T)
00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
|
二、建立引用視圖(相似於關係表建立一個從表)
1
2
|
CREATE VIEW empview AS SELECT MAKE_REF(deptview,department_id) deptOID,employee_id,
first_name,last_name FROM emp;
|
查詢對象視圖empview
1
2
3
4
5
6
7
8
9
10
11
12
13
|
SQL> SELECT * FROM empview;
DEPTOID
EMPLOYEE_ID FIRST_NAME LAST_NAME
00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
100 Steven King
00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
101 Neena Kochhar
00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
102 Lex De Haan
00004A038A004667BAC3685B444520A60ED30027E8F25F0000001426010001000100290000000000090604002A00078401FE
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 * FROM STUDENTS WHERE STUDENT.SEX = ''F'' 這樣會報以下錯誤:ORA-00904: "STUDENT"."SEX": 標識符無效
對象類型表:每條記錄都是對象的表,稱爲對象類型表.它有兩個使用方法:1,用做只有一個對象類型字段的表.2,用做具備對象類型字段的標準關係表.
語法以下:
CREATE TABLE table_name OF object_type;
例如:
CREATE TABLE TMP_STUDENTS OF HUMAN;
用DESC TMP_STUDENTS,能夠看到它的字段結構和HUMAN的結構同樣.
對象類型表有兩個優勢:1,從某種程度上簡化了對象的使用,由於對象表的字段類型與對象類型是一致的,因此,不須要用對象名來修飾對象屬性,能夠把數據插入對象類型表,就像插入普通的關係表中同樣:
INSERT INTO TMP_STUDENTS VALUES (''xling'',''M'',TO_DATE(''20060601'',''YYYYMMDD''),''對象類型表'');
固然也可用以下方法插入:
INSERT INTO TMP_STUDENTS VALUES (HUMAN(''snow'',''F'',TO_DATE(''20060102'',''YYYYMMDD''),''用類型的構造函數''));
第二個特色是:對象表是使用對象類型做爲模板來建立表的一種便捷方式,它能夠確保多個表具備相同的結構.
對象類型表在:USER_TABLES表裏是查不到的,而在USER_OBJECTS表裏能夠查到,並且OBJECT_TYPE = ''TABLE''
類型在定義的時候,會自動包含一個方法,即默認的構造器.構造器的名稱與對象的名稱相同,它帶有變量與對象類型的每一個屬性相對應.
對象類型的方法:
CREATE TYPE type_name AS OBJECT (
column1 column_type1,
column2 column_type2,
... ,
MEMBER FUNCTION method_name(args_list) RETURN return_type,
...
)
注意:是MEMBER FUNCTION,(固然,也但是MEMBER PROCEDURE,沒有返回值)
和包(PACKAGE)同樣,若是對象類型有方法的話,還要聲明一個BODY:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
CREATE TYPE BODY type_name AS
MEMBER FUNCTION method_name RETURN return_type { AS | IS }
variable declareations..
BEGIN
CODE..
RETURN return_value;
END ;// END MEMBER FUNCTION
...
END ;// END TYPE BODY
CREATE TYPE HUMAN AS OBJECT(
NAME VARCHAR2(20),
SEX VARCHAR2(1),
BIRTHDAY DATE ,
NOTE VARCHAR2(300),
MEMBER FUNCTION GET_AGE RETURN NUMBER
)
CREATE TYPE BODY HUMAN AS
MEMBER FUNCTION GET_AGE RETURN NUMBER AS
V_MONTHS NUMBER;
BEGIN
SELECT FLOOR(MONTHS_BETWEEN(SYSDATE,BIRTHDAY)/12) INTO V_MONTHS FROM DUAL;
RETURN V_MONTHS;
END ;
END ;
|
注意:BODY的格式,不是AS OBJECT,也不是用小括號括起來的.MEMBER FUNCTION 後的AS或IS不能省略.
還以STUDENTS表爲例(注:若是類型以被某個表使用,是不能修改的,必須把相關的表刪除,而後把類型刪除,在一個一個新建,這裏就省略了,參見前文所述)
SELECT S.STUDENT.GET_AGE() FROM STUDENTS S
在提起注意:表名必定要有別名.GET_AGE()的括號不能省略,不然會提示錯誤.
下面演示在一個匿名過程當中的使用狀況:
SET SERVEROUTPUT ON
DECLARE
AA HUMAN;
AGE NUMBER;
BEGIN
AA := HUMAN(''xingFairy'',''M'',TO_DATE(''19830714'',''YYYYMMDD''),''過程'');
AGE := AA.GET_AGE();
DBMS_OUTPUT.PUT_LINE(AGE);
END;
映射方法:
映射方法是一種不帶參數,並返回標準的標量Oracle SQL數據類型的方法,如NUMBER,VARCHAR2,Oracle將間接地使用這些方法執行比較運算.
映射方法最重要的一個特色是:當在WHERE或ORDER BY等比較關係子句中使用對象時,會間接地使用映射方法.
映射方法的聲明只過是在普通方法聲明的前面加一個 MAP而以,注意:映射方法是一種不帶參數的方法.
MAP MEMBER FUNCTION function_name RETURN return_type
修改前文提到的HUMAN類型:
--映射方法 MAP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
CREATE TYPE HUMAN AS OBJECT(
NAME VARCHAR2(20),
SEX VARCHAR2(1),
BIRTHDAY DATE ,
REGISTERDAY DATE ,
NOTE VARCHAR2(300),
MEMBER FUNCTION GET_AGE RETURN NUMBER,
MAP MEMBER FUNCTION GET_GRADE RETURN NUMBER
)
CREATE TYPE BODY HUMAN AS
MEMBER FUNCTION GET_AGE RETURN NUMBER AS
V_MONTHS NUMBER;
BEGIN
SELECT FLOOR(MONTHS_BETWEEN(SYSDATE,BIRTHDAY)/12) INTO V_MONTHS FROM DUAL;
RETURN V_MONTHS;
END ;
MAP MEMBER FUNCTION GET_GRADE RETURN NUMBER AS
BEGIN
RETURN MONTHS_BETWEEN(SYSDATE,BIRTHDAY);
END ;
END ;
|
插入數據:
1
2
3
|
INSERT INTO STUDENTS (STUDENT) VALUES (HUMAN( '' xling '' , '' M '' ,TO_DATE( '' 19830714 '' , '' YYYYMMDD '' ),TO_DATE( '' 20020915 '' , '' YYYYMMDD '' ), '' 測試MAP方法 '' ));
INSERT INTO STUDENTS (STUDENT) VALUES (HUMAN( '' fairy '' , '' M '' ,TO_DATE( '' 19830714 '' , '' YYYYMMDD '' ),TO_DATE( '' 20010915 '' , '' YYYYMMDD '' ), '' 測試MAP方法 '' ));
INSERT INTO STUDENTS (STUDENT) VALUES (HUMAN( '' snow '' , '' M '' ,TO_DATE( '' 19830714 '' , '' YYYYMMDD '' ),TO_DATE( '' 20020915 '' , '' YYYYMMDD '' ), '' 測試MAP方法 '' ));
|
在執行上面的操做後,用下面這個SELECT語句能夠看出映射方法的效果:
SELECT S.STUDENT.NAME,S.STUDENT.GET_GRADE() FROM STUDENTS S ORDER BY STUDENT
它是按MAP方法GET_GRADE()的值進行排序的.注意是ORDER BY STUDENT,在提起一次須要注意,必定要用表的別名,方法後的括號不能省略,即便沒有參數.
若是想以MAP方法的結果爲條件,能夠以下:
1
2
|
SELECT S.STUDENT. NAME ,S.STUDENT.GET_GRADE() FROM STUDENTS S WHERE S.STUDENT.GET_GRADE() > 50
SELECT S.STUDENT. NAME ,S.STUDENT.GET_GRADE() FROM STUDENTS S WHERE STUDENT > HUMAN( NULL , NULL , NULL ,TO_DATE( '' 20020101 '' , '' YYYYMMDD '' ), NULL );
|
排序方法:
先說一下SELF,Oracle裏對象的SELF和JAVA裏的this是同一個意思.
對象的排序方法具備一個與對象類型相同的參數,暫稱爲ARG1,用於和SELF對象進行比較.若是調用方法的SELF對象比ARG1小,返回負值,若是相等,返回0,若是SELF大於ARG1,則返回值大於0.
--映射方法 MAP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
CREATE TYPE HUMAN AS OBJECT(
NAME VARCHAR2(20),
SEX VARCHAR2(1),
BIRTHDAY DATE ,
REGISTERDAY DATE ,
NOTE VARCHAR2(300),
MEMBER FUNCTION GET_AGE RETURN NUMBER,
ORDER MEMBER FUNCTION MATCH(I_STUDENT IN HUMAN) RETURN NUMBER
)
CREATE TYPE BODY HUMAN AS
MEMBER FUNCTION GET_AGE RETURN NUMBER AS
V_MONTHS NUMBER;
BEGIN
SELECT FLOOR(MONTHS_BETWEEN(SYSDATE,BIRTHDAY)/12) INTO V_MONTHS FROM DUAL;
RETURN V_MONTHS;
END ;
ORDER MEMBER FUNCTION MATCH(I_STUDENT IN HUMAN) RETURN NUMBER AS
BEGIN
RETURN REGISTERDAY - I_STUDENT.REGISTERDAY;
END ;
END ;
|
注意:在聲明的時候,ORDER方法的參數類型要和SELF的類型一致.
SET SERVEROUTPUT ON
DECLARE
S1 HUMAN;
S2 HUMAN;
BEGIN
S1 := HUMAN(''xling'',NULL,NULL,TO_DATE(''20020915'',''YYYYMMDD''),NULL);
S2 := HUMAN(''snow'',NULL,NULL,TO_DATE(''20010915'',''YYYYMMDD''),NULL);
IF S1 > S2 THEN
DBMS_OUTPUT.PUT_LINE(S1.NAME);
ELSIF S1 < S2 THEN
DBMS_OUTPUT.PUT_LINE(S2.NAME);
ELSE
DBMS_OUTPUT.PUT_LINE(''EQUAL'');
END IF;
END;
注意S1 和 S2是怎麼比較的.
映射方法具備效率方面的優點,由於它把每一個對象與單個標量值聯繫在一塊兒;排序方法有靈活方面的優點,它能夠在兩個對象之間進行任意複雜的比較.排序方法比映射方法的速度慢.
實例:
(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 TABLE OF 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 TABLE OF sales_gender_t;
(5) 也可使用基本類型定義 表類型好比:
1
2
|
create or replace type test_tab_type as table of varchar2(4000);
/
|
varchar2(4000) 是一個資本類型,這樣至關於定義的表中只有一個字段varchar2(4000)
用法:
1
2
3
4
5
6
|
TYPE sales_country_t_rec IS RECORD (
YEAR VARCHAR (4),
country CHAR (2),
sum_amount_sold NUMBER
);
v_sales_country_t_rec sales_country_t_rec;
|
引用:
1
2
3
|
v_sales_country_t_rec. year := 'ssss' ;
v_sales_country_t_rec.country := 'a' ;
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 ,person t_air);
3 插入數據
insert into aaa values(1,t_air(1,'23sdf'));
4 查詢classPlace
select a.id ,a.persion.id,a.person.name from aaa a;
t_air(1,'23sdf') 使用這個方式建立一個自定義類型t_air的對象.
------------------------------------------------------------
三:下面簡單的枚舉下經常使用的幾種自定義類型。
一、子類型。 這種類型最簡單,相似類型的一個別名,主要是爲了對經常使用的一些類型簡單化,它基於原始的某個類型。如: 有些應用會常常用到一些貨幣類型:number(16,2)。若是在全局範圍各自定義這種類型,一旦須要修改該類型的精度,則須要一個個地修改。 那如何實現定義的全局化呢?因而就引出了子類型: subtype cc_num is number(16,2); 這樣就很方便地解決了上述的麻煩。
整理:
http://blog.csdn.net/qfs_v/article/details/2446941
http://blog.csdn.net/feimashenhua/article/details/7177948
http://blog.itpub.net/12932950/viewspace-662514
http://psoug.org/reference/type.html