oracle中物件型別蒐集(object type)
/* 物件型別屬於使用者自定義的一種複合型別,它封裝了資料結構和擁有操作這些資料結構的函式。
物件型別;物件型別體和物件型別規範組成
物件型別屬性不能使用以下型別定義。如;long,rowid,%type,%rowtype,ref cursor,record, pls_integer等
涉及到成員方法。構造方法,靜態方法,map方法(將物件型別進行比較,因為物件不像標量那樣可以直接排序),最大隻能定義一個map 方法
map方法可以對個物件進行排序,而order方法只能對兩個物件例項比較大小 ,map和order不能同時定義。
《1》物件表
物件表是包含物件型別列的表,而普通表其列全部使用標量資料型別。分為行物件表和列物件表
eg; create table obj_emp of emp_type;
2.列物件(包含多個列)
eg; create table obj_emp(
dno number,dname varchar2(10),
emp emp_type
);
《2》物件型別繼承
《3》引用物件型別 ref(指向物件的邏輯指標,是oracle的一種內建資料型別)(通過引用可以使不同表共享相同物件,從而降低記憶體佔用)
如 create table obj_emp2 (
emp ref obj_emp --引用上面的行物件
);
《4》建立物件型別
1.建立無方法的物件型別
create or replace type emp_type as object (
name varchar2(8),
birthdate date
);
--建立行物件表
create table emp_tab of emp_type ;
insert into emp_tab values('tom',to_date('1980-1-25','yyyy-mm-dd'));--普通插入
insert into emp_tab values(emp_type('sam',to_date('1983-1-25','yyyy-mm-dd'))); --採用物件型別構造方法插入
-- 在pl/sql塊中,如果要將物件資料檢索到物件變數中,則必須用value方法
declare
emp emp_type;
begin
select value(p) into emp from emp_tab p where p.name = '&name';
dbms_output.put_line(emp.birthdate);
end;
-- 更新行物件資料,如果根據物件屬性更新資料時必須定義物件別名
eg; update emp_tab p set p.birthdate=to_date('2000-1-23',yyyy-mm-dd) where p.name=&name;
-- 刪除行物件型別資料是如果根據物件屬性刪除資料 ,則刪除時必須定義別名
begin
delete from emp_tab p where p.name=&name;
end;
/
==============================================================================================
-- 建立列物件表
create or replace type emp_l_tab as object (
dname varchar2(),emp emp_type
);
-- insert (用物件型別的構造方法插入資料)
insert into emp_l_tab values('db' emp_type('tom',to_date('2011-06-14',sysdate)));
-- 檢索列物件
檢索行物件型別資料到型別變數時必須用value方法,但檢索列物件時可以直接檢索到型別變數
declare
v_emp_l emp_type ;
v_dname varchar2(20) ;
select dname,emp into v_dname,emp from emp_l_tab b where b.dname=&dname;
--更新列物件時,必須為列物件定義別名(列物件別名.物件型別列名.物件屬性名)
update emp_l_tab b set b.emp.birthdate = to_date('2011-06-14','yyyy-mm-dd') where b.dname=&dame;
--刪除類同更新資料
2.建立有方法的物件型別
1》 建立和使用member(成員)方法的物件型別(建立物件型別規範)
eg;
create or replace type emp_m_type as object(
dname varchar2(20), ddate date,addr varchar2(100),
member procdure proc_change_addr(newaddr dname),
member function func_get_dname return varchar2
);
/
2》建立物件型別體
create or replace type body emp_m_type is
member procdure proc_change_addr(newaddr varchar2)
is
begin
addr ;= newaddr;
end;
member function func_get_dname return varchar2
is
v_dname varchar2(20);
begin
v_danme := '部門:'||dname ||'--'|| birthdate ;
return v_danme;
end;
end;
/
-- 插入資料類同上面
-- 提前資料
declare
v_emp emp_m_type;
begin
v_emp ;= emp.get_dname('上海徐匯');
......................
end;
/
--3 建立和使用static 方法
static 方法用於訪問物件型別,如果需要在物件型別上執行全域性操作,則應該定義static
方法。只能有物件型別訪問static
create or replace type emp_type3 as object(
name varchar2(10),gender varchar2(2),
static function getname return varchar2,
member function get_gender return varchar2
);
--建立物件型別體
create or replace type body emp_type3 is
static function getname return varchar2 is
begin
return 'jecker';
end;
member function get_gender return varchar2
is
begin
return 'xingbie='||gender;
end;
end;
;
-- 基於物件型別emp_type3 建立 emp_tab3
create table emp_tab3(
eno number(6),emp emp_type3,
sal number(6,2),job varchar2(10)
);
-- 向表emp_tab3插入資料
begin
insert into emp_tab3(eno,sal,job,emp)
values(100001,9999,'CTO/CIO',emp_type3(
'jeckery',emp_type3.getname()
));
end;
-- 訪問 靜態static函式和成員方法(member)
declare
e emp_type3;
begin
select t.emp into e from emp_tab3 t where rownum=1;
raise_application_error(-20201,emp_type3.getname()||'-----'||e.get_gender());
end;
-- 4.建立和使用 map 方法
map方法用於將物件例項對映成標量值。
-- 建立物件型別emp_type4
create or replace type emp_type4 as object(
name varchar2(10),
birthdate date,
map member function get_birdate return varchar2
);
-- 為emp_type4 物件型別實現方法體
create or replace type body emp_type4 is
map member function get_birdate return varchar2 is
begin
return trunc((sysdate-birthdate)/365);
end;
end;
-- 根據物件型別empa_type4 建立表emp_tab4
create table emp_tab4 (
eno number(6),sal number(6,2),
job varchar2(20),emp4 emp_type4
);
-- 插入資料到emp_tab4
begin
insert into emp_tab4(eno,sal,job,emp4)
values(0011,9000,'dba',emp_type4('jacker',to_date('1990-12-19','yyyy-mm-dd')));
insert into emp_tab4(eno,sal,job,emp4)
values(0022,9900,'dba',emp_type4('jacker',to_date('1970-12-2','yyyy-mm-dd')));
end;
--比較資料
declare
type emp4_tab is table of emp_type4;
v_emp4_tab emp4_tab;
v_result varchar2(100);
begin
select emp4 bulk collect into v_emp4_tab from emp_tab4 ;
if v_emp4_tab(1).get_birdate()>v_emp4_tab(2).get_birdate() then
v_result := v_emp4_tab(1).name ||' 比 '||v_emp4_tab(2).name ||'大';
else
v_result := v_emp4_tab(1).name ||' 比 '||v_emp4_tab(2).name ||'小';
end if;
raise_application_error(-20201,v_result);
end;
-- 5 建立order 方法
1.order 與 map 在一個物件型別中不能同時存在
2.order 用於比較物件的2個例項大小
-- 建立物件型別emp_type4
create or replace type emp_type5 as object(
name varchar2(10),
birthdate date,
order member function compare(emp5 emp_type5) return int
);
-- 為emp_type4 物件型別實現方法體
create or replace type body emp_type5 is
order member function compare(emp5 emp_type5) return int is
begin
case
when birthdate>emp5.birthdate then return 1;
when birthdate=emp5.birthdate then return 0;
when birthdate<emp5.birthdate then return -1;
end case;
end;
end;
-- 根據物件型別empa_type4 建立表emp_tab4
create table emp_tab5 (
eno number(6),sal number(6,2),
job varchar2(20),emp5 emp_type5
);
-- 插入資料到emp_tab4
begin
insert into emp_tab5(eno,sal,job,emp5)
values(0011,9000,'dba',emp_type5('jacker',to_date('1990-12-19','yyyy-mm-dd')));
insert into emp_tab5(eno,sal,job,emp5)
values(0022,9900,'dba',emp_type5('tom',to_date('1970-12-2','yyyy-mm-dd')));
end;
--比較資料
declare
type emp5_tab is table of emp_type5;
v_emp5_tab emp5_tab;
v_result varchar2(100);
begin
select emp5 bulk collect into v_emp5_tab from emp_tab5 ;
if v_emp5_tab(1).compare(v_emp5_tab(2))=1 then
v_result := v_emp5_tab(1).name ||' 比 '||v_emp5_tab(2).name ||'大';
else
v_result := v_emp5_tab(1).name ||' 比 '||v_emp5_tab(2).name ||'小';
end if;
raise_application_error(-20201,v_result);
end;
-- 6. 建立包含自定義物件型別的構造方法
oracle 9i 開始可以自定義建構函式
create or replace type emp_type6 as object(
name varchar2(10),birthdate date,
constructor function emp_type6(name,varchar2) return self as result;
);
方法體的實現類同5
==========================================================================================
《2》複雜物件型別
1.巢狀物件型別:一個物件型別中巢狀另一個物件型別
create or replace typed emp_addr_type7 as object(
addr varchar2(100)
);
eg;
create or replace typed emp_type7 as object(
name varchar2(10), emp_addr emp_addr_type7
);
2.參照物件型別:建立物件表時 使用ref 定義表列,ref實際是指向物件資料的邏輯指標。
........
《3》檢視物件型別
1.檢視物件型別
select type_name ,final from user_types;
2.修改物件型別
alter type emp_type7 add atrribute addr varchar2(10) cascade;
...
Oracle type object 物件型別 繼承,參考官方文件:
oracle create type object inherit
2.3.5.2 Creating a Subtype Object
A subtype inherits the attributes and methods of the supertype.
These are inherited:
-
All the attributes declared in or inherited by the supertype.
-
Any methods declared in or inherited by supertype.
defines the student_typ
object as a subtype of person_typ
, which inherits all the attributes declared in or inherited by person_typ
and any methods inherited by or declared in person_typ
.
Example 2-15 Creating a student_typ Subtype Using the UNDER Clause
- -- requires Ex. 2-14
- CREATE TYPE student_typ UNDER person_typ (
- dept_id NUMBER,
- major VARCHAR2(30),
- OVERRIDING MEMBER FUNCTION show RETURN VARCHAR2)
- NOT FINAL;
- /
- CREATE TYPE BODY student_typ AS
- OVERRIDING MEMBER FUNCTION show RETURN VARCHAR2 IS
- BEGIN
- RETURN (self AS person_typ).show || ' -- Major: ' || major ;
- END;
- END;
- /
The statement that defines student_typ
specializes person_typ
by adding two new attributes, dept_id
and major
and overrides the show
method. New attributes declared in a subtype must have names that are different from the names of any attributes or methods declared in any of its supertypes, higher up in its type hierarchy.
原
Oracle Object type 物件型別
2013年08月05日 12:17:11 閱讀數:8292
版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/bbliutao/article/details/9765469
Oracle Object type 物件型別
一、概述
Oracle物件型別是Oracle面向物件程式設計的體現,它封裝了資料結構和用於操縱這些資料結構的過程和函式。
1、物件型別的組成
物件型別由兩部分組成——物件型別頭和物件型別體。
物件型別頭用於定義物件的公用屬性和方法;物件型別體用於實現物件型別頭所定義的公用方法。
2、物件型別屬性
定義物件型別最少要包含一個屬性,最多包含1000個屬性。定義時必須提供屬性名和資料型別,但不能指定預設值和not null。
資料型別不能包括long、long raw、rowid、urowid和PL/SQL特有型別(boolean\%type\%rowtype\ref curdor等)
3、物件型別的方法
定義物件型別可以包含也可以不包含方法,可以定義構造方法、member方法、static方法、map方法和order方法。
1)、構造方法
用於初始化物件並返回物件例項。構造方法是與物件型別同名的函式,預設的構造方法引數是物件型別的所有屬性。
9i前只能使用系統預設的構造方法、9i後可自定義建構函式,自定義必須使用constructor function關鍵字
2)、member方法
用於訪問物件例項的資料。當使用member方法時,可以使用內建引數self訪問當前物件例項。
當定義member方法時,無論是否定義self引數,它都會被作為第一個引數傳遞給member方法。
但如果要定義引數self,那麼其型別必須要使用當前物件型別。member方法只能由物件例項呼叫,而不能由物件型別呼叫。
3)、static方法
用於訪問物件型別,可以在物件型別上執行全域性操作,而不需要訪問特定物件例項的資料,因此static方法引用self引數。
static方法只能由物件型別呼叫,不能由物件例項呼叫(和member相反)。
4)、map方法
物件型別不同於標量型別可以直接比較,為了按照特定規則排序物件例項的資料,可以定義map方法,但只能有一個,與order互斥。
map方法將物件例項對映成標量數值來比較。
5)、order方法
map可以在對多個物件例項之間排序,而order只能比較2個例項的大小。定義物件型別時最多隻能定義一個order方法,
而且map和order方法不能同時定義。使用原則是可不用則均不用,比較2個物件則用order,對個物件則用map。
4、物件表
物件表是指至少包含一個物件型別列的表。分為行物件表和列物件表。
行物件表是指直接基於物件型別所建立的表;列物件表則是隻包含一個或多個列的物件表。
5、REF資料型別
ref是指向行物件的邏輯指標,是Oracle的一種內建資料型別。建表時通過使用REF引用行物件,可以使不同表共享相同物件。
例如:create table department(dno number(2),dname varchar2(10),emp ref employee_type)
二、物件型別的基本應用
1、概述
基本應用也屬於最常規、最簡單的應用,講述如何建立和使用獨立的並且與其他物件型別無關的物件型別。
包括語法、建立帶方法和不帶方法的物件型別。
2、語法
create or replace type type_name as object (
v_name1 datatype[,v_name2 datatype,...],
[member|static method1 spec,member|static method2 spec,...]);
create or replace type body type_name as
member|static method1 body;
member|static method1 body;...
其中,type_name是物件型別的名稱,v_name是屬性名稱,datatype是屬性資料型別,method是方法的名稱,body是PL/SQL的方法實現程式碼。
如果定義物件型別頭時沒有定義方法,則不需要建立物件型別體。
3、建立和使用不包含任何方法的物件型別
--建立物件型別
create or replace type person_typ1 as object(name varchar2(10),gender varchar2(2),birthdate date);
1)、對於行物件表
--建立行物件表
create table persong_tab1 of person_typ1;
--插入
begin
insert into person_tab1 values('馬麗','女','11-1月-76');--不用構造方法
insert into person_tab1 values(person_typ1('王鳴','男','12-2月-76'));--用構造方法
end;
--查詢,必須使用value函式取得行資料
declare
person person_typ1;
begin
select value(p) into person from person_tab1 p where p.name='&name';
dbms_output.put_line(person.gender||','||person.birthdate);
end;
--更新
begin
update person_tab1 p set b.birthdate='11-2月-76' where p.name='馬麗';
end;
--刪除
begin
delete from person_tab1 p where p.name='馬麗';
end;
2)、對於列物件表
--建立列物件表
create table employee_tab1(eno number(6),person person_typ1,sal number(6.2),job varchar2(10));
--插入,必須使用構造方法(預設構造方法)
begin
insert into employee_tab1(eno,sal,job,person) values(1,2000,'高階電工',person_typ1('王鳴','男'.'01-8月-76'));
end;
--查詢
declare
employee person_typ1;
salary number(6,2);
begin
select person,sal into employee,salary from employee_tab1 where eno=&no;
dbms_output.put_line(employee.name||','||salary);
end;
--更新
begin
update employee_tab1 p set p.person.birthdate='&newdate' where p.person.name='&name';
end;
--刪除
begin
delete from employee_tab1 p where p.person.name='王鳴';
end;
4、建立和使用包含方法的物件型別
--建立物件型別頭
create or replace type person_typ2 as object
(
name varchar2(10),
gender varchar2(2),
birthdate date,
address varchar2(100),
regdate date,
member procedure change_address(new_addr varchar2),--member方法
member function get_info return varchar2,--member方法
static function getdate return date,--static方法
map member function getage return varchar2,--map方法
order member function compare(p person_typ2) return int,--order方法
constructor person typ2(name varchar2) return self as result,
constructor person typ2(name varchar2,gender varchar2) return self as result
);
--建立物件型別體
create or replace type body person_typ2 is
member procedure change_address(new_addr varchar2) is
begin
address := new_addr; --member方法體現之處,直接訪問修改物件例項的資料address
end;
member function get_info return varchar2 is
v_info varchar2(100);
begin
v_info := name || ',' || birthdate || ',' || regdate;
return v_info;
end;
static function gerdate return date is
begin
return sysdate;
end;
map member function getage return varchar2 is
begin
return trunc((sysdate-birthdate)/365);--比較的依據是按照時間
end;
order member function compare(p person_typ2) return int is
begin
case
when birthdate>p.birthdate then return 1;
when birthdate=p.birthdate then return 0;
when birthdate>p.birthdate then return -1;
end case;
end;
constructor function person_typ2(name varchar2) return self as result is
begin
self.name:=name;
self.gender:='女';
self.birthdate:=sysdate;
return;
end;
constructor function person_typ2(name varchar2,gender varchar2) return self as result is
begin
self.name:=name;
self.gender:=gender;
self.birthdate:=sysdate;
return;
end;
end;
--建立列物件表
create table employee_tab2(eno number(6),person person_typ2,sal number(6,2),job varchar2(10));
--插入
insert into employee_tab2(eno,sal,job,person) values(1,1500,'圖書管理員',
person_typ2('馬麗','女','11-1月-75','呼和浩特11號',person_typ2.getdate()));--由物件型別呼叫的全域性方法getdate(static方法)
insert into employee_tab2(eno,sal,job,person) values(2,2000,'高階焊工',
person_typ2('王鳴','男','11-5月-75','呼和浩特21號',person_typ2.getdate()));
insert into employee_tab2(eno,sal,job,person) values(3,3000,'高階工程師',
person_typ2('李奇','男','11-5月-70','呼和浩特31號',person_typ2.getdate()));
insert into employee_tab2(eno,sal,job,person) values(3,3000,'高階工程師',person_typ2('怪獸');--自定義構造方法
insert into employee_tab2(eno,sal,job,person) values(3,3000,'高階工程師',person_typ2('怪獸','男');
--呼叫
declare
v_person person_typ2;
type person_table_type is table of person_typ2;
person_table person_table_type;
begin
select person into v_person from employee_tab2 where eno = &&no;
v_person.change_address('呼和浩特12號');
update employee_tab2 set person = v_person where eno = &no;
dbms_output.put_line(v_person.get_info);
--map,取表中前2條資料來對比
select person bulk collect into person_table from employee_tab2;
if person_table(1).getage()>person_table(2).getage() then
dbms_output.put_line(person_table(1).name||'比'||person_table(2).name||'大');
else
dbms_output.put_line(person_table(2).name||'不比'||person_table(1).name||'大');
end if;
--compare
if person_table(1).compare(person_table(2))=1 then
dbms_output.put_line(person_table(1).name||'比'||person_table(2).name||'大');
else
dbms_output.put_line(person_table(2).name||'不比'||person_table(1).name||'大');
end if;
end;
三、物件型別的高階應用
1、概述
高階應用簡述與其他物件型別具有關聯關係的物件型別。包括物件型別的巢狀、參照物件型別、物件型別的繼承。
2、物件型別的巢狀
1)、建立物件型別addr_typ7
create or replace type addr_typ7 as object(
state varchar2(20),city varchar2(20),street varchar2(50),zipcode(6),
member function get_addr return varchar2);
create or replace type body addr_typ7 as
member function get_addr return varchar2 is
begin
return state||city||street;
end;
end;
2)、建立物件型別person_typ7,巢狀addr_typ7物件型別
create or replace type person_typ7 as object(
name varchar2(10),gender varchar2(2),birthdate date,
address addr_typ7,member function get_info return varchar2);
create or replace type body person_typ7 as
member function get_info return varchar2 is
begin
return '姓名:'||name||',家庭住址'||address.get_addr();
end;
end;
3)、建立列物件表employee_tab7
create table employee_tab7(eno number(6),person person_typ7,sal number(6,2),job varchar2(10));
4)、插入
insert into employee_tab7(eno,sal,job,person) values
(1,1500,'圖書管理員',person_typ7('馬麗','女','01-11月-76',addr_typ7('內蒙古自治區','呼和浩特市','呼倫北路22號','010010')));
insert into employee_tab7(eno,sal,job,person) values
(2,2000,'高階鉗工',person_typ7('王鳴','男','11-12月-75',addr_typ7('內蒙古自治區','呼和浩特市','呼倫北路50號','010010')));
5)、更新
declare
v_person person_typ7;
begin
select person into v_person from employee_tab7 where eno=1;
v_person.address.street:='北恆東街11號';
update employee_tab7 set person=v_person where eno=1;
end;
6)、查詢
declare
v_person_typ7;
begin
select person into v_person from employee_tab7 where eno=1;
dbms_output.put_line(v_person.get_info);
end;
6)、刪除
begin
delete from employ33_tab7 where eno=1;
end;
3、參照物件型別
1)、概述
參照物件型別是指在建立物件表時使用REF定義表列,REF實際是指向行物件表資料的指標。
通過使用REF定義表列,可以使得一個物件表引用另一個物件表(行物件表)的資料。
2)、建立物件型別person_typ8
create or replace type person_typ8 as object(
name varchar2(10),gender varchar2(2),birthdate date,address varchar2(100),
member function get_info return varchar2
);
create or replace type body person_typ8 as
member function get_info return varchar2 is
begin
return name||',0'||address;
end;
end;
3)、建立行物件表person_tab8
create table person_tab8 of person_typ8;
insert into person_tab8 values('馬麗','女','11-1月-75','呼和浩特11號');
insert into person_tab8 values('王鳴','男','11-5月-75','呼和浩特21號');
4)、建立列物件表employee_tab8
說明:employee_tab8表直接引用person_tab8表的資料。
create table employee_tab8(
eno number(6),person ref person_typ8,sal number(6,2),job varchar2(10));
5)、插入
說明:因為employee_tab8的定義使用ref引用了person_tab8,所以插入需要引用該表資料。,使用函式REF
begin
insert into employee_tab8 select 1,ref(a),2000,'圖書管理員' from person_tab8 a where a.name='馬麗';
insert into employee_tab8 select 2,ref(a),2000,'高階鉗工' from person_tab8 a where a.name='王鳴';
end;
6)、查詢
說明:取ref物件列資料,必須使用deref。
declare
v_person person_typ8;
begin
select deref(person) into v_person from employee_tab8 where eno=1;
dbms_output.put_line(v_person.get_into);
end;
7)、更新
declare
v_person person_typ8;
begin
select deref(perosn) into v_person from employee_tab8 where eno=1;
v_person.address:='呼和浩特市神馬路';
update person_tab8 set address=v_person.address where name=v_person.name;
end;
8)、刪除
begin
delete from employee_tab8 where eno=1;
end;
4、物件型別的繼承
1)、概述
9i新增,一個物件型別繼承另一個物件型別。定義需要被繼承的父類時需要指定not final,否則預設final,表示物件型別不能被繼承。
2)、建立物件型別person_typ9
create or replace type person_typ9 as object(
name varchar2(10),gender varchar2(2),birthdate date,address varchar2(100),
member function get_info return varchar2
) not final;
create or replace type body person_typ8 as
member function get_info return varchar2 is
begin
return name||',0'||address;
end;
end;
3)、建立子物件型別
create or replace type employee_typ9 under person_typ9(
eno number(6),sal number(6,2),job varchar2(10),
member function get_other return varchar2);
create or replace type body employee_typ9 as
member function get_other return varchar2 is
begin
return name||','||sal;
end;
end;
4)、建立行物件表
create table employee_tab9 of employee_typ9;
insert into person_tab8 values('馬麗','女','11-1月-75','呼和浩特11號',1,1500,'圖書管理員');
insert into person_tab8 values('王鳴','男','11-5月-75','呼和浩特21號',2,2000,'高階鉗工');
5)、查詢
declare
v_employee employee_typ9;
begin
select value(a) into v_employee from employee_tab9 a where a.eno=1;
dbms_output.put_line(v_employee.get_info||','||v_employee.get_other);
end;
四、維護物件型別
1、顯示物件型別資訊
select type_name,attributes,final from user_types;
2、增刪物件型別的屬性
alter type person_typ1 add attribute address varchar2(50) cascade;
alter type person_typ1 drop attribute birthdate cascade;
--cascade級聯更新依賴物件型別的物件型別和物件表。
3、增刪物件型別的方法
alter type person_typ1 add member function get info return varchar2 cascade;
create or replace type body person_typ1 as
member function get_info return varchar2 is
begin
return name||','||address;
end;
end;
原文:
轉
Oracle TYPE OBJECT詳解
2014年06月13日 13:24:58 閱讀數:532
轉自:http://blog.csdn.net/indexman/article/details/8435426
以下同:
Oracle TYPE OBJECT詳解
2012-12-26 11:43:33
收藏
TYPE OBJECT詳解
======================================================
最近在自學PL/SQL高階,瞭解到物件型別(OBJECT TYPE)。
www.2cto.com
特意搜尋了一下10G官方文件,下面不才基於此進行拓展:
=======================================================
1. 介紹
Object-oriented programming is especially suited for building reusable components and complex
applications.
尤其適合於構建可重用的部件和複雜的應用程式的面向物件的程式設計。
www.2cto.com
In PL/SQL, object-oriented programming is based on object types.
在PL / SQL,面向物件的程式設計是基於物件型別。
They let you model real-world objects, separate interfaces and implementation details, and store
object-oriented data persistently in the database.
他們堅持讓你模擬現實世界的物件,單獨的介面和實現細節,面向物件的資料和儲存在中。
2. PL / SQL的宣告和初始化物件
物件的型別可以代表任何真實世界的實體。例如,一個物件的型別可以代表一個學生,銀行帳戶,電腦螢幕上
,合理數量,或資料結構,如佇列,堆疊,或列表。
[sql]
CREATE OR REPLACE TYPE address_typ AS OBJECT (
street VARCHAR2(30),
city VARCHAR2(20),
state CHAR(2),
postal_code VARCHAR2(6)
);
[sql]
CREATE OR REPLACE TYPE employee_typ AS OBJECT(
employee_id NUMBER(6),
first_name VARCHAR2(20),
last_name VARCHAR2(25),
email VARCHAR2(25),
phone_number VARCHAR2(25),
hire_date DATE,
job_id VARCHAR2(25),
salary NUMBER(8,2),
commission_pct NUMBER(2,2),
manager_id NUMBER(6),
department_id NUMBER(4),
address address_typ
MAP MEMBER FUNCTION get_idno RETURN NUMBER,
MEMBER PROCEDURE display_address(SELF IN OUT NOCOPY employee_typ)
);
--建立物件體
[sql]
CREATE TYPE BODY employee_typ AS
MAP MEMBER FUNCTION get_idno RETURN NUMBER IS
BEGIN
RETURN employee_id;
END;
MEMBER PROCEDURE display_address ( SELF IN OUT NOCOPY employee_typ ) IS
BEGIN
DBMS_OUTPUT.PUT_LINE(first_name || ' ' || last_name);
DBMS_OUTPUT.PUT_LINE(address.street);
DBMS_OUTPUT.PUT_LINE(address.city || ', ' || address.state || ' ' ||
address.postal_code);
END;
END;
--持久化物件
[sql]
CREATE TABLE employee_tab OF employee_typ;
CREATE TYPE emp_typ as table of employee_typ;
3. 在PL/SQL塊中宣告物件:
[sql]
DECLARE
emp employee_typ; -- emp is atomically null
BEGIN
-- call the constructor for employee_typ
emp := employee_typ(315, 'Francis', 'Logan', 'FLOGAN',
'555.777.2222', to_date('2012-12-24', 'yyyy-mm-dd'), 'SA_MAN', 11000, .15, 101, 110,
address_typ('376 Mission', 'San Francisco', 'CA', '94222'));
DBMS_OUTPUT.PUT_LINE(emp.first_name || ' ' || emp.last_name); -- display details
emp.display_address(); -- call object method to display details
END;
4. PL/SQL如何處理未初始化的物件:
[sql]
DECLARE
emp employee_typ; -- emp is atomically null
BEGIN
IF emp IS NULL THEN DBMS_OUTPUT.PUT_LINE('emp is NULL #1'); END IF;
IF emp.employee_id IS NULL THEN
DBMS_OUTPUT.PUT_LINE('emp.employee_id is NULL #1');
END IF;
emp.employee_id := 330;
IF emp IS NULL THEN DBMS_OUTPUT.PUT_LINE('emp is NULL #2'); END IF;
IF emp.employee_id IS NULL THEN
DBMS_OUTPUT.PUT_LINE('emp.employee_id is NULL #2');
END IF;
emp := employee_typ(NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
address_typ(NULL, NULL, NULL, NULL));
-- emp := NULL; -- this would have made the following IF statement TRUE
IF emp IS NULL THEN DBMS_OUTPUT.PUT_LINE('emp is NULL #3'); END IF;
IF emp.employee_id IS NULL THEN
DBMS_OUTPUT.PUT_LINE('emp.employee_id is NULL #3');
END IF;
EXCEPTION
WHEN ACCESS_INTO_NULL THEN
DBMS_OUTPUT.PUT_LINE('Cannot assign value to NULL object');
END;
5. 在PL/SQL中操縱物件:
5.1.呼叫物件構造器和方法(Calling Object Constructors and Methods)
[sql]
DECLARE
emp employee_typ;
BEGIN
INSERT INTO employee_tab VALUES (employee_typ(310, 'Evers', 'Boston', 'EBOSTON',
'555.111.2222', to_date('2012-12-24', 'yyyy-mm-dd'), 'SA_REP', 9000, .15, 101, 110,
address_typ('123 Main', 'San Francisco', 'CA', '94111')) );
INSERT INTO employee_tab VALUES (employee_typ(320, 'Martha', 'Dunn', 'MDUNN',
'555.111.3333', to_date('2012-11-5', 'yyyy-mm-dd'), 'AC_MGR', 12500, 0, 101, 110,
address_typ('123 Broadway', 'Redwood City', 'CA', '94065')) );
END;
5.2 更新和刪除物件:
[sql]
DECLARE
emp employee_typ;
BEGIN
INSERT INTO employee_tab VALUES (employee_typ(370, 'Robert', 'Myers', 'RMYERS',
'555.111.2277', to_date('2012-3-7', 'yyyy-mm-dd'), 'SA_REP', 8800, .12, 101, 110,
address_typ('540 Fillmore', 'San Francisco', 'CA', '94011')) );
UPDATE employee_tab e SET e.address.street = '1040 California'
WHERE e.employee_id = 370;
DELETE FROM employee_tab e WHERE e.employee_id = 310;
END;
6. 通過REF修飾符操縱物件:
[sql]
DECLARE
emp employee_typ;
emp_ref REF employee_typ;
emp_name VARCHAR2(50);
BEGIN
SELECT REF(e) INTO emp_ref FROM employee_tab e WHERE e.employee_id = 370;
-- the following assignment raises an error, not allowed in PL/SQL
-- emp_name := emp_ref.first_name || ' ' || emp_ref.last_name;
-- emp := DEREF(emp_ref); not allowed, cannot use DEREF in procedural statements
SELECT DEREF(emp_ref) INTO emp FROM DUAL; -- use dummy table DUAL
emp_name := emp.first_name || ' ' || emp.last_name;
DBMS_OUTPUT.PUT_LINE(emp_name);
END;
7. 定義相當於PL/SQL集合型別的SQL型別(Defining SQL Types Equivalent to PL/SQL Collection Types)
7.1 定義巢狀表:
--建巢狀表型別
CREATE TYPE CourseList AS TABLE OF VARCHAR2(10) -- define type
--建物件型別
CREATE TYPE student AS OBJECT ( -- create object
id_num INTEGER(4),
name VARCHAR2(25),
address VARCHAR2(35),
status CHAR(2),
courses CourseList); -- declare nested table as attribute
--建立巢狀表型別表
CREATE TABLE sophomores of student
NESTED TABLE courses STORE AS courses_nt;
--插入資料
insert into sophomores
values(1,'dylan','CARL STREET','ACTIVE',
CourseList('MATH1020')
);
--查詢
SELECT a.*, b.*
from sophomores a, TABLE(a.courses) b;
select /*+ nested_table_get_refs */ *
from courses_nt t;
7.2 定義陣列:
-- 宣告陣列型別(Each project has a 16-character code name)
-- We will store up to 50 projects at a time in a database column.
CREATE TYPE ProjectList AS VARRAY(50) OF VARCHAR2(16);
--建立表
CREATE TABLE dept_projects ( -- create database table
dept_id NUMBER(2),
name VARCHAR2(15),
budget NUMBER(11,2),
-- Each department can have up to 50 projects.
projects ProjectList);
--插入資料:
INSERT INTO dept_projects
VALUES(60, 'Security', 750400,
ProjectList('New Badges', 'Track Computers', 'Check Exits'));
8. 在動態SQL中使用物件:
8.1 定義物件型別person_typ和陣列型別hobbies_var,並建立報TEAMS:
[sql]
CREATE TYPE person_typ AS OBJECT (name VARCHAR2(25), age NUMBER);
CREATE TYPE hobbies_var AS VARRAY(10) OF VARCHAR2(25);
CREATE OR REPLACE PACKAGE teams
AUTHID CURRENT_USER AS
PROCEDURE create_table (tab_name VARCHAR2);
PROCEDURE insert_row (tab_name VARCHAR2, p person_typ, h hobbies_var);
PROCEDURE print_table (tab_name VARCHAR2);
END;
CREATE OR REPLACE PACKAGE BODY teams AS
PROCEDURE create_table (tab_name VARCHAR2) IS
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE ' || tab_name ||
' (pers person_typ, hobbs hobbies_var)';
END;
PROCEDURE insert_row (
tab_name VARCHAR2,
p person_typ,
h hobbies_var) IS
BEGIN
EXECUTE IMMEDIATE 'INSERT INTO ' || tab_name ||
' VALUES (:1, :2)' USING p, h;
END;
PROCEDURE print_table (tab_name VARCHAR2) IS
TYPE refcurtyp IS REF CURSOR;
v_cur refcurtyp;
p person_typ;
h hobbies_var;
BEGIN
OPEN v_cur FOR 'SELECT pers, hobbs FROM ' || tab_name;
LOOP
FETCH v_cur INTO p, h;
EXIT WHEN v_cur%NOTFOUND;
-- print attributes of 'p' and elements of 'h'
DBMS_OUTPUT.PUT_LINE('Name: ' || p.name || ' - Age: ' || p.age);
FOR i IN h.FIRST..h.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('Hobby(' || i || '): ' || h(i));
END LOOP;
END LOOP;
CLOSE v_cur;
END;
END;
8.2 呼叫TEAMS包中的儲存過程:
[sql]
DECLARE
team_name VARCHAR2(15);
BEGIN
team_name := 'Notables';
TEAMS.create_table(team_name);
TEAMS.insert_row(team_name, person_typ('John', 31),
hobbies_var('skiing', 'coin collecting', 'tennis'));
TEAMS.insert_row(team_name, person_typ('Mary', 28),
hobbies_var('golf', 'quilting', 'rock climbing', 'fencing'));
TEAMS.print_table(team_name);
END;
=================================================
output:
Name: John - Age: 31
Hobby(1): skiing
Hobby(2): coin collecting
Hobby(3): tennis
Name: Mary - Age: 28
Hobby(1): golf
Hobby(2): quilting
Hobby(3): rock climbing
Hobby(4): fencing
PL/SQL 過程已成功完成。