技术开发 频道

Oracle中的OOP概念

  【IT168 技术文档】

  Oracle 中的OOP概念:

  对象类型,可变数组,嵌套表,对象表,对象视图

  对象类型:

  优点:

  1) 更容易与Java, C++编写的对象应用程序交互

  2) 获取便捷。一次对象类型请求就可以从多个关系表中获取信息,通过一次网络往复即可返回

  语法:

  CREATE [OR REPLACE] TYPE type_name

  {{AS| IS } OBJECT | UNDER super_type}

  {

  attribute_name datatype[,attribute_name datatype]… ---成员变量

  [{MAP | ORDER} MEMBER function_name,] ---排序函数

  [{FINAL | NOT FINAL} MEMBER function_name,] ---可否继承的成员函数

  [{INSTANTIABLE | NOT INSTANTIABLE } MEMBER function_name,] ---可否实例化的成员函数

  [{MEMBER | STATIC } function_name,] ---静态、非静态成员函数

  }

  [{FINAL | NOT FINAL}] ---对象可否继承

  [{INSTANTIABLE | NOT INSTANTIABLE }] ---对象可否实例化

  /

  对象类型的主体部分(即函数的实现部分,可选的):

  CREATE [OR REPLACE]

  TYPE BODY type_name {AS| IS }

  [{MAP | ORDER} MEMBER function_body,] ---排序函数

  [{MEMBER | STATIC } function_name,] ---静态、非静态成员函数

  END;

  /

  例如:

  create or replace

  type person as object(

  first_name varchar2(100),

  last_name varchar2(100))

  /

  属性类型可以是任何oracle 数据类型(包括自定义),除了如下:

  LONG和LONG RAW

  NCHAR、NCLOB 、NVARCHAR2

  ROWID、UROWID

  PL/SQL的特定类型:%TYPE %ROWTYPE

  查看:

  Desc person

  构造函数:

  set serveroutput on

  declare

  l_person person

  begin

  l_person := person(‘Donny’,’Chen’);

  dbms_output.putline(l_person.first_name);

  end;

  /

  构造函数要接受对象类型的所有属性作为参数。因为这些参数没有默认值,即使是null,也要提供。

  举例:

  表中的对象类型:

  对象类型可以作为数据库中的列,所以称为列对象

  create table person_table

  (

  name person,

  age number)

  /

  set desc depth all

  desc person_table

  set desc depth 1

  插入数据:

  insert into person_table

  values(person(‘Donny’,’Chen’),30);

  declare

  l_person person

  begin

  l_person := person(‘Hua’,’Li’);

  insert into person_table values(l_person,33);

  end;

  /

  查询数据:

  select * from person_table

  访问对象类型的各个属性:

  select p.name.first_name

  from person_table p

  /

  为避免名称解析问题,要求查询对象类型的属性的时候,使用表别名。否则报错,举例:

  对象中的对象(合成):

  create or replace

  type employee as object(

  name person,

  empno number,

  hiredate date)

  修改和删除对象:

  9i之前,当建立的对象类型,以及依赖于此类型的对象或表之后,就无法再修改此对象类型了(增加删除属性和成员函数)。唯一的办法是撤销所有以来,即删除依赖于此类型的对象或表。

  9i新特性,可以修改被以来的对象类型,成为类型演化。有两种方法:

  INVALIDATE 和 CASCADE

  INVALIDATE比如:

  desc person_table

  改变person类型,增加新属性ssn

  alter type person

  add attribute ssn varchar2(11) INVALIDATE;

  desc person (bug可能需要新开一个session)

  INVALIDATE选项使的所有依赖于person类型的对象和表标记为INVALID,比如:

  Desc person_table

  需要手工验证person_table:

  alter table person_table upgrade including data;

  desc person_table

  upgrade including data表示根据新类型,物理上更新现有的数据的结构,ssn 置为null。

  也可以upgrade not including data,不更新原有数据的结构。Dml访问person实例数据的时候再更新。

  Select * from person_table

  CASCADE比如:

  alter type person

  add attribute dob date

  cascade not including table data

  /

  不用手工验证依赖此对象类型的表,由数据库自动验证。

  Desc person

  Desc person_table

  因为not including table data,没有更新原有数据:

  select * from person_table

  删除类型:

  force

  方法:

  即对象中的过程和函数,3种类型:

  STATIC: 只能够在对象类型上调用,不专属于某个实例。

  MEMBER: 专属于某个特定的实例

  CONSTRUCTOR: 构造函数

  create or replace

  type employee as object(

  name person,

  empno number,

  hiredate date,

  sal number,

  commission number,

  member function total_compensation return number,

  static function new(p_empno number,

  p_person person) return employee)

  /

  desc employee

  在类型主体实现这两个方法:

  create or replace

  type body employee as

  member function total_compensation return number is

  begin

  return nvl(self.sal,0) + nvl(self.commission, 0);

  end;

  static function new(p_empno number,

  p_person person) return employee is

  begin

  return employee(p_person,p_empno,sysdate,10000,null);

  end;

  end;

  /

  比较抽象数据类型的数据:

  declare

  l_employee1 employee;

  l_employee2 employee;

  begin

  l_employee1 :=employee.new(12345,null);

  l_employee2 :=employee.new(67890,null);

  if l_employee1= l_employee2 then

  dbms_output.line_put(“They are equal”);

  end if;

  end;

  /

  使用map指定具体比较哪些属性:

  create or replace

  type employee as object(

  name person,

  empno number,

  hiredate date,

  sal number,

  commission number,

  map member function convert return number)

  /

  create or replace

  type body employee as

  map member function convert return number is

  begin

  return self.empno;

  end;

  end;

  /

  再比较:

  declare

  l_employee1 employee;

  l_employee2 employee;

  begin

  l_employee1 :=employee.new(12345,null);

  l_employee2 :=employee.new(67890,null);

  if l_employee1= l_employee2 then

  dbms_output.line_put(“They are equal”);

  end if;

  if l_employee1> l_employee2 then

  dbms_output.line_put(“employee1 is greater”);

  end if;

  if l_employee1< l_employee2 then

  dbms_output.line_put(“employee2 is greater”);

  end if;

  end;

  /

  Order 方法:

  create or replace

  type employee as object(

  name person,

  empno number,

  hiredate date,

  sal number,

  commission number,

  order member function match(p_employee employee) return integer)

  /

  create or replace

  type body employee as

  order member function match(p_employee employee) return integer is

  begin

  if self.empno> p_employee.empno then

  return 1;

  elseif self.empno< p_employee.empno then

  return -1;

  else

  return 0;

  end if;

  end;

  end;

  /

  继承:

  FINAL / NOT FINAL

  对象默认FINAL,表示不可以被继承;

  MEMBER方法也能指定是否FINAL,表示能否在子类中对他进行覆写。默认NOT FINAL

  Create or replace type super_type as object(

  N number,

  Final member procedure cannot_override

  )

  not final

  /

  create or replace type sub_type under super_type(

  overriding member procedure cannot_override

  )

  /

  show error

  若super_type 改成final

  INSTANTIABLE / NOT INSTANTIABLE

  可否被实例化,后者类似于抽象类

  create or replace type shape as object(

  number_of_sides number,

  not instantiable member function calculate_area return number

  )

  not instantiable not final

  /

  实例化该类型对象:

  declare

  l_shape shape;

  begin

  l_shape:=shape(2);

  end;

  /

  可变数组(VARRAYS):

  create type employee_type as object(

  employee_id number,

  first_name varchar2(30),

  last_name varchar2(30)

  )

  /

  create type employee_list_type as varray(50) of employee_type

  /

  create table departments(

  department_id number,

  department_name varchar2(30),

  manager employee_type,

  employees employee_list_type)

  /

  insert into departments values

  (10,

  ‘HR’,

  employee_type(1,’Dony’,’Chen’),

  employee_list_type(

  employee_type(2,’Hua’,’Li’)

  employee_type(3,’Wu’,’Wang’)

  employee_type(4,’San’,’Zhang’))

  )

  /

  column department_name format a13

  column employee_type format a63 word_wrapped

  select * from departments

  /

  嵌套表(Nested table):

  create type order_item_type as object(

  line_item_id number(3),

  product_id number(6),

  unit_price numbe(8,2),

  quantity number(4)

  )

  /

  create type order_item_list_type as table of order_item_type

  /

  create table orders(

  order_id number(12) not null,

  order_date date,

  customer_id number(6),

  order_items order_item_list_type)

  nested table order_items store as order_items_tab

  /

  insert into orders values(

  (1, sysdate, 10,

  order_item_list_type(

  order_item_type(1,2,3,4),

  order_item_type(2,3,4,5)

  ))

  /

  多少个order_item_type ,无限制。

  对象表:

  每行都代表一个对象,行对象

  创建对象:

  create or replace

  type address as object(

  id number,

  street varchar2(100),

  state varchar2(2),

  zipcode varchar2(11)

  )

  /

  创建对象表:

  create table address_table of address

  /

  desc address_table

  插入数据:

  可以像关系表一样插入

  insert into address_table values(1,’Oracle way’,’CA’,’90001’)

  /

  也可以用默认构造函数插入对象:

  insert into address_table

  values(address(2,’Oracle way2’,’CA’,’90011’)

  select * from address_ table

  /

  VALUE()

  以对象表别名作为参数,返回对象实例:

  select value(a) from address_table a

  /

  REF数据类型:

  在关系表中关联对象

  create table employee_location(

  empno number,

  loc_ref ref address scope is address_table)

  /

  loc_ref是个列,类型是指向address对象类型的ref, 即引用,或者指向address实例的指针。

  scope is address_table 是可选的,表示ref指向的对象实例的位置,即只能指向address_table对象表中的address对象实例。

  REF():

  REF()函数可以建立指向对象表中对象实例的REF对象数据类型,以对象表的别名作为参数

  插入数据:

  insert into employee_location

  select 12345, ref(a)

  from address_table a

  where id=1

  /

  insert into employee_location

  select 45678, ref(a)

  from address_table a

  where id=2

  /

  OID:

  对象表中每一行对象都对应一个唯一的OID,对象标示符

  Select * from employee_location

  DEREF()

  解析REF数据类型,返回真正指向的实例。以REF数据类型作为参数

  select empno, deref(loc_ref)

  from employee_location

  悬空REF:

  REF指向的对象实例被删掉了,此时称REF悬空(dangling),说明ref指向不存在的实例

  Delete from address_table where id=1;

  Select * from employee_location;

  Select empno, deref(rec_loc) from employee_location;

  悬空的ref会返回null,使用is dangling 确定哪些ref悬空:

  select empno from employee_location

  where loc_ref is dangling;

  清除悬空的ref, 将ref更新为null:

  update employee_location

  set loc_ref =null

  where loc_ref is dangling;

  Select * from employee_location;

  对象视图:

  在已有的关系型表上,建立对象模型:

  关系表:

  create table item

  ( itemcode varchar2(10),

  item_on_hand number(10),

  item_sode number(10)

  );

  建立对象,使用相同的列:

  create or replace type item_type as object

  ( itemcode varchar2(10),

  item_on_hand number(10),

  item_sode number(10)

  );

  建立对象视图:

  create view item_view of item_type

  with object oid (itemcode)

  as

  select * from item

  /

  of item_type 说明基于对象

  with object oid (itemcode) 明确生成OID

  通过视图操作数据:

  insert into item_view values(item_type(‘i102’,15,50));

  MAKE_REF()

  关系主表1:

  create table itmefile(

  itemcode varchar2(5) primary key,

  itemdesc varchar2(20),

  p_category varchar2(20),

  qty_hand number(5),

  re_level number(5),

  max_level number(5),

  itemrate number(9,2));

  关系从表2:

  create table order_detail(

  orderno varchar2(5),

  itemcode varchar2(5) foreign key references itemfile(itemcode)

  qty_ord number(5),

  qty_deld number(5)

  )

0
相关文章