`
刘金剑
  • 浏览: 145339 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

PL\SQL用户指南与参考10.2 转载

阅读更多

5、对象类型实例:实数

有理数能够表现成两个整数相除的形式,一个分子和一个分母。同大多数语言一样,PL/SQL并没有实数类型或是用于实数操作的预定义操作符。现在让我们就用对象类型来弥补这个缺失。首先,编写下面的对象说明:

CREATE  TYPE  rational AS  OBJECT(
  num   INTEGER ,
  den   INTEGER ,
  MAP MEMBER FUNCTION  CONVERT
    RETURN  REAL ,
  MEMBER PROCEDURE  normalize,
  MEMBER FUNCTION  reciprocal
    RETURN  rational,
  MEMBER FUNCTION  plus(x rational)
    RETURN  rational,
  MEMBER FUNCTION  LESS(x rational)
    RETURN  rational,
  MEMBER FUNCTION  times(x rational)
    RETURN  rational,
  MEMBER FUNCTION  divby(x rational)
    RETURN  rational,
  PRAGMA  RESTRICT_REFERENCES(DEFAULT , RNDS, WNDS, RNPS, WNPS)
);

PL/SQL不允许操作符重载。所以我们必须定义方法plus(),less()(minus是保留关键字),times()和divby()来替代操作符+、-、*和/。

下一步,创建下面的独立存储函数,它们会被方法normalize()调用:

CREATE  FUNCTION  gcd(x INTEGER , y INTEGER )
  RETURN  INTEGER  AS
  -- find greatest common divisor of x and y
  ans   INTEGER ;
BEGIN
  IF  (y <= x) AND (x MOD  y = 0) THEN
    ans    := y;
  ELSIF  x < y THEN
    ans    := gcd(y, x);   -- recursive call
  ELSE
    ans    := gcd(y, x MOD  y);   -- recursive call
  END  IF ;

  RETURN  ans;
END ;

下面是对象类型体的内容:

CREATE  TYPE  BODY  rational AS
  MAP MEMBER FUNCTION  CONVERT
    RETURN  REAL  IS
  -- convert rational number to real number
  BEGIN
    RETURN  num / den;
  END  CONVERT;
  MEMBER PROCEDURE  normalize IS
    -- reduce fraction num / den to lowest terms
    g   INTEGER ;
  BEGIN
    g      := gcd(num, den);
    num    := num / g;
    den    := den / g;
  END  normalize;
  MEMBER FUNCTION  reciprocal
    RETURN  rational IS
    -- return reciprocal of num / den
  BEGIN
    RETURN  rational(den, num);   -- call constructor
  END  reciprocal;
  MEMBER FUNCTION  plus(x rational)
    RETURN  rational IS
    -- return sum of SELF + x
    r   rational;
  BEGIN
    r    := rational(num * x.den + x.num * den, den * x.den);
    r.normalize;
    RETURN  r;
  END  plus;
  MEMBER FUNCTION  LESS(x rational)
    RETURN  rational IS
    -- return difference of SELF - x
    r   rational;
  BEGIN
    r    := rational(num * x.den - x.num * den, den * x.den);
    r.normalize;
    RETURN  r;
  END  LESS;
  MEMBER FUNCTION  times(x rational)
    RETURN  rational IS
    -- return product of SELF * x
    r   rational;
  BEGIN
    r    := rational(num * x.num, den * x.den);
    r.normalize;
    RETURN  r;
  END  times;
  MEMBER FUNCTION  divby(x rational)
    RETURN  rational IS
    -- return quotient of SELF / x
    r   rational;
  BEGIN
    r    := rational(num * x.den, den * x.num);
    r.normalize;
    RETURN  r;
  END  divby;
END ;

七、声明并初始化对象

只要对象类型在模式中定义了,我们就可以在任何PL/SQL块、子程序或包中引用它来声明对象。例如,我们可以使用对象类型作为属性、字段、变量、绑定变量、记录的域、表元的素、形式参数或函数返回值的数据类型。在运行时,对象类型的实例会被创建,也就是对象实例被初始化。

1、定义对象

我们可以在使用内置类型(如CHAR或NUMBER)的地方使用对象类型。在下面的块中,我们声明了Rational类型的对象r。然后调用构造函数初始化对象,把值6和8分别赋给属性num和den。

DECLARE
  r   rational;
BEGIN
  r    := rational(6, 8);
  DBMS_OUTPUT.put_line(r.num);   -- prints 6
END ;

我们还可以把对象作为函数和过程的形式参数。那样就能把对象从一个子程序传递到另一个子程序了。在下面的例子中,我们使用对象类型Account作为形式参数:

DECLARE
  ...
  PROCEDURE  open_acct (new_acct IN  OUT  Account) IS  ...

下面,我们把Accout作为函数的返回类型来使用:

DECLARE
  ...
  FUNCTION  get_acct (acct_id IN  INTEGERRETURN  Account IS  ...

2、初始化对象

如果不调用构造函数初始化对象,那它会被自动赋上空值。也就是说对象本身为空,不单单指它的属性。如下例:

DECLARE
  r   rational;   -- r becomes atomically null
BEGIN
  r    := rational(2, 3);   -- r becomes 2/3
END ;

一个空对象总不能等于另一个对象。实际上,拿一个空对象与另一个对象比较结果总是NULL.同样,如果把一个空对象或NULL赋给另一个对象,那么被赋值的对象也为空,示例如下:

DECLARE
  r   rational;
BEGIN
  r    := rational(1, 2);   -- r becomes 1/2
  r    := NULL ;   -- r becomes atomically null
  IF  r IS  NULL  THEN  ...   -- condition yields TRUE

一个好的编程习惯就是在声明的时候就为对象初始化,例如:

DECLARE
  r Rational := Rational(2,3);   -- r becomes 2/3

3、PL/SQL如何对待未初始化对象

在表达式中,未初始化的对象属性值为NULL。如果为一个未初始化的对象属性赋值,就会引起预定义异常ACCESS_INTO_NULL。当对未初始化的对象或是它的属性使用IS NULL做比较时,结果总为TRUE。

下面的例子就演示了空对象和含有空属性的对象之间的差异:

DECLARE
  r   rational;   -- r is atomically null
BEGIN
  IF  r IS  NULL  THEN  ...   -- yields TRUE
  IF  r.num IS  NULL  THEN  ...   -- yields TRUE
  r        := rational(NULLNULL );   -- initializes r
  r.num    := 4;   -- succeeds because r is no longer atomically null
  -- even though all its attributes are null
  r        := NULL ;   -- r becomes atomically null again
  r.num    := 4;   -- raises ACCESS_INTO_NULL
EXCEPTION
  WHEN  ACCESS_INTO_NULL THEN
    ...;
END ;

调用一个未初始化对象的方法会引起预定义异常NULL_SELF_DISPATCH。如果把未初始化对象的属性作为IN模式参数进行传递时,就跟传递一个NULL参数一样;如果把它作为OUT或IN OUT模式参数传递,并且尝试为其赋值,就会引起异常。

八、访问属性

我们只能按名称来引用属性,不可以使用它的位置来进行引用。在下面的例子中,我们先把属性den赋给变量denominator,然后把变量numerator的值赋给属性num。

DECLARE
  r             rational := rational(NULLNULL );
  numerator     INTEGER ;
  denominator   INTEGER ;
BEGIN
  ...
  denominator    := r.den;
  r.num          := numerator;
END ;

下面再看一个稍微复杂一点的对象嵌套例子:

CREATE  TYPE  address AS  OBJECT(
  street     VARCHAR2 (30),
  city       VARCHAR2 (20),
  state      CHAR (2),
  zip_code   VARCHAR2 (5)
);

CREATE  TYPE  student AS  OBJECT(
  NAME           VARCHAR2 (20),
  home_address   address,
  phone_number   VARCHAR2 (10),
  status         varcahr2(10),
  advisor_name   VARCHAR2 (20),
  ...
);

这里要注意的是,zip_code是对象类型Address的一个属性,而Address又是对象Student的属性home_address的数据类型。如果s是Student的对象的话,我们就可以像下面这样访问它的zip_code属性:

s.home_address.zip_code

九、定义构造函数

默认情况下,我们不需要为对象类型定义构造函数,因为系统会提供一个接受与每个属性相对应的参数的构造函数。

我们也许想定义自己的构造函数:

  1. 为某些属性提供默认值,这样就能确保属性值的正确性而不必依赖于调用者所提供的每一个属性值。
  2. 避免许多特殊用途的过程只初始化对象的不同部分。
  3. 当新的属性加到对象类型中时,避免更改调用构造函数的应用程序中的代码。构造函数也许需要一些新的代码,例如把属性设置为空,但我们还需要保持方法签名不变,这样可以使已存在的构造函数调用继续工作。
CREATE  OR  REPLACE TYPE  rectangle AS  OBJECT(
  -- The type has 3 attributes.
  LENGTH   NUMBER ,
  width    NUMBER ,
  area     NUMBER ,
  -- Define a constructor that has only 2 parameters.
  CONSTRUCTOR FUNCTION  rectangle(LENGTH NUMBER , width NUMBER )
    RETURN  SELF AS  RESULT
);
/

CREATE  OR  REPLACE TYPE  BODY  rectangle AS
  CONSTRUCTOR FUNCTION  rectangle(LENGTH NUMBER , width NUMBER )
    RETURN  SELF AS  RESULT AS
  BEGIN
    SELF.LENGTH    := LENGTH;
    SELF.width     := width;
    -- We compute the area rather than accepting it as a parameter.
    SELF.area      := LENGTH * width;
    RETURN ;
  END ;
END ;
/

DECLARE
  r1   rectangle;
  r2   rectangle;
BEGIN
  -- We can still call the default constructor, with all 3 parameters.
  r1    := NEW  rectangle(10, 20, 200);
  -- But it is more robust to call our constructor, which computes
  -- the AREA attribute. This guarantees that the initial value is OK.
  r2    := NEW  rectangle(10, 20);
END ;
/

十、调用构造函数

只要是能够调用普通函数的地方,我们就可以调用构造函数。跟所有的函数一样,构造函数也可以作为表达式的一部分而被调用,如下例所示:

DECLARE
  r1   rational := rational(2, 3);

  FUNCTION  average(x rational, y rational)
    RETURN  rational IS
  BEGIN
    ...
  END ;
BEGIN
  r1    := average(rational(3, 4), rational(7, 11));

  IF  (rational(5, 8) > r1) THEN
    ...
  END  IF ;
END ;

当我们为构造函数传递参数的时候,调用会把对象中需要初始化的属性赋上初始值。如果是调用默认的构造函数,我们就需要为每个属性指定一个初始值;跟常量和变量不同,属性是不可以有默认值的。下例中,第n个参数为第n个属性赋值:

DECLARE
  r   rational;
BEGIN
  r    := rational(5, 6);   -- assign 5 to num, 6 to den
  -- now r is 5/6

十一、调用方法

跟打包子程序一样,方法也是使用点标志来调用的。示例如下:

DECLARE
  r   rational;
BEGIN
  r    := rational(6, 8);
  r.normalize;
  DBMS_OUTPUT.put_line(r.num);   -- prints 3
END ;

如下例所示,我们可以连续调用方法。执行顺序从左到右。首先,成员函数reciprocal()会被调用,然后成员过程normalize()被调用。

DECLARE
  r   rational := rational(6, 8);
BEGIN
  r.reciprocal().normalize;
  DBMS_OUTPUT.put_line(r.num);   -- prints 4
END ;

在SQL语句中,调用无参数的方法需要使用一个空的参数列表。在过程化语句中,空的参数列表是可选的,除非我们使用链式调用,这时除了最后一个调用之外其他的都需要空的参数列表。

我们不能把过程作为连续调用的一部分,因为过程是作为语句使用而不是表达式。所以,像下面这样的语句是不允许的:

r.normalize().reciprocal;   -- not allowed

同样,如果连续调用两个函数,第一个函数必须返回一个能传入第二个函数的对象。对于静态方法,我们使用下面的语法:

type_name.method_name

这种调用是不需要对象实例的。从子类实例中调用方法时,实际执行的方法是由类的继承关系决定的。如果子类覆盖了基类的方法,子类的方法就会被调用;否则的话,基类的方法会被调用。这种情况称为动态方法分派。

十二、通过REF修饰符共享对象

在真实世界中的大多数对象都要比有理数类型庞大而且复杂。如果对象比较大的话,把对象副本从一个子程序传递到另一个子程序时效率就可能会很低。这时如果使用对象共享就很有意义了,我们可以使用一个指向对象的引用来引用所需要的对象。

共享有两个重要的好处。首先,避免了不必要的数据重复。其次,在共享的对象内容更新时,任何引用所指向的内容也会被立即更新。如下面的例子:

CREATE  TYPE  home AS  OBJECT(
  address      VARCHAR2 (35),
  owner        VARCHAR2 (25),
  age          INTEGER ,
  style        VARCHAR (15),
  floor_plan   BLOB,
  price        REAL (9, 2),
  ...
);
/

CREATE    TABLE  homes OF  home;

修改一下Person,我们就能建立家庭的模型,几个人共享一个家。我们可以使用修饰符REF来声明引用:

CREATE  TYPE  person AS  OBJECT(
  first_name     VARCHAR2 (10),
  last_name      VARCHAR2 (15),
  birthday       DATE ,
  home_address   REF  home,   -- can be shared by family
  phone_number   VARCHAR2 (15),
  ss_number      INTEGER ,
  mother         REF  person,   -- family members refer to each other
  father         REF  person,
  ...
);

我们可以把变量、参数、字段或属性声明为引用。而且,我们还可以在SQL数据操作语句中把引用当作输入或输出变量使用。但是,我们不可以通过引用调用对象的内容。比如表达式x.attribute,其中x是一个引用,PL/SQL无法找到存放对象的数据表。例如,下面的赋值语句就是不允许的:

DECLARE
  p_ref      REF  person;
  phone_no   VARCHAR2 (15);
BEGIN
  phone_no    := p_ref.phone_number;   -- not allowed
END ;

解决办法就是用函数DEREF或调用包UTL_REF来访问对象。

1、向前类型定义

我们只能引用已经存在的模式对象。下例中,第一个CREATE TYPE语句是不允许的,因为它引用的Department并不存在:

CREATE  TYPE  employee AS  OBJECT(
  NAME   VARCHAR2 (20),
  dept   REF  department,   -- not allowed
  ...
);

CREATE  TYPE  department AS  OBJECT(
  "number"   INTEGER ,
  manager    employee,
  ...
);

把上面两个CREATE TYPE语句调换位置也不会起作用,因为这两个对象类型是互相依赖的。对象类型Employee有着一个Department类型的属性,而 Department又同样有着一个Employee类型的属性。为了解决这个问题,我们应该使用特殊的CREATE TYPE语句,我称它为向前类型定义,这样我们就可以互相引用两个独立的对象类型。现在使用下面的语句:

要调试上面的例子,我们只要把下面的语句提前即可:

CREATE  TYPE  Department;   -- forward type definition
-- at this point, Department is an incomplete object type

向前类型定义创建的对象类型被称为不完全对象类型(incomplete object type),因为它没有属性和方法。一个不纯的不完全对象类型有属性,但编译时会发生错误,因为它引用了一个未确定的类型。例如,下面的CREATE TYPE语句就会因对象类型Address未确定而出错:

CREATE  TYPE  Customer AS  OBJECT (
  id     NUMBER ,
  name   VARCHAR2 (20),
  addr   Address,   -- not yet defined
  phone  VARCHAR2 (15)
);

如果使用了向前声明,我们就可以推迟对象类型Address的定义,并且,不完全类型Customer也可以被其他应用程序的开发者引用。

十三、操作对象

我们可以在CREATE TABLE语句中把某个字段指定为对象类型。一旦表被建立,我们就可以用SQL语句把对象插入表中,选取它的属性,调用它的方法更新它的状态。

注意:访问远程的或分布式对象都是不允许的。

在下面SQL*Plus脚本中,INSERT语句调用对象类型Rational的构造函数,然后插入resulting对象。SELECT语句检索属性num的值。UPDATE语句调用成员方法reciprocal(),在交换属性num和den之后,返回Retional的值。要注意的是,在引用属性或方法时,表别名是必须的。

CREATE  TABLE  numbers (rn Rational, ...)
/
INSERT  INTO  numbers (rn) VALUES  (Rational(3, 62))   -- inserts 3/62
/
SELECT  n.rn.num INTO  my_num FROM  numbers n ...   -- returns 3
/
UPDATE  numbers n SET  n.rn = n.rn.reciprocal() ... --   yields 62/3

用这种方法初始化对象时,对象在数据库表之外是没有标识的。但是,对象类型是独立于表而存在的,可以用其他方式创建对象。

下例中,我们创建一个存放对象类型Retional的表。这样包含对象类型的表称为对象表。一行中的每一列都与对象的属性对应。行与行间的列值是不同的。

CREATE  TABLE  rational_nums OF  Rational;

对象表中每行都有一个对象标识,能够唯一辨识一个存放在数据库中的对象。

1、查询对象

假定我们要在SQL*Plus中运行下面的脚本,创建一个对象类型Person和一个对象表persons,并且我们为该表填充一些数据:

CREATE  TYPE  person AS  OBJECT(
  first_name     VARCHAR2 (15),
  last_name      VARCHAR2 (15),
  birthday       DATE ,
  home_address   address,
  phone_number   VARCHAR2 (15)
)
/

CREATE  TABLE  persons OF  person
/

下面子查询能产生一个只包含Person对象属性的结果集:

BEGIN
  INSERT  INTO  employees   -- another object table of type Person
    SELECT  *
      FROM  persons p
     WHERE  p.last_name LIKE  '%Smith' ;

要返回对象结果集,我们就必须使用VALUE函数。

  • 使用VALUE函数

跟我们所期望的一样,函数VALUE能返回对象值。VALUE会把一个相关的变量作为它的参数。(在这里,相关变量就是行变量或与对象表中的一行相关联的表别名)。例如,要返回Person对象的结果集,要向下面这样使用VALUE:

BEGIN
  INSERT  INTO  employees
    SELECT  VALUE(p)
      FROM  persons p
     WHERE  p.last_name LIKE  '%Smith' ;

在下面的例子中,我们可以使用VALUE来返回一个特定的Person对象:

DECLARE
  p1   person;
  p2   person;
  ...
BEGIN
  SELECT  VALUE(p)
    INTO  p1
    FROM  persons p
   WHERE  p.last_name = 'Kroll' ;

  p2    := p1;
  ...
END ;

p1是一个本地的Person对象,它是名为"Kroll"的存储对象的一个副本,而p2是另一个本地Person对象,它是p1的副本。如下例所示,我们可以使用这些变量来访问和更新它们所引用的对象:

BEGIN
  p1.last_name    := p1.last_name || ' Jr' ;
END ;

现在,本地的Person对象p1的名字为"Kroll Jr"。

  • 使用REF函数

我们可以用函数REF来检索引用,同VALUE一样,它也把一个相关的变量作为它的参数。下例中,我们检索一个或多个指向Person对象的引用,然后把引用插入表person_refs中:

BEGIN
  INSERT  INTO  person_refs
    SELECT  REF (p)
      FROM  persons p
     WHERE  p.last_name LIKE  '%Smith' ;
END ;

下面的例子我们同时检索一个引用和一个属性:

DECLARE
  p_ref         REF  person;
  taxpayer_id   VARCHAR2 (9);
BEGIN
  SELECT  REF (p), p.ss_number
    INTO  p_ref, taxpayer_id
    FROM  persons p
   WHERE  p.last_name = 'Parker' ;   -- must return one row
  ...
END ;

在最后一个例子中,我们更新一个Person对象的属性:

DECLARE
  p_ref          REF  person;
  my_last_name   VARCHAR2 (15);
BEGIN
  SELECT  REF (p)
    INTO  p_ref
    FROM  persons p
   WHERE  p.last_name = my_last_name;

  UPDATE  persons p
     SET  p = person('Jill''Anders''11-NOV-67' , ...)
   WHERE  REF (p) = p_ref;
END ;
  • 测试dangling引用

如果一个引用所指向的对象被删除了,那么它就会指向一个不存在的对象,我们称这样的引用为dangling引用。要测试这种情况,我们应该使用 SQL的IS DANGLING语句。假设关系表department的manager字段引用了对象表中的Employee对象。我们就可以使用下面的UPDATE语句来把"dangling"引用转为空值:

UPDATE  department
   SET  manager = NULL
 WHERE  manager IS  DANGLING;
  • 使用DEREF函数

我们不可以在PL/SQL过程语句中。(DEREF是dereference的缩写。当我们反引用一个指针时,我们就能获取它所指向的值。) DEREF把对象的引用作为它的参数值,然后返回这个引用所指向的对象。如果引用是"dangling"的,DEREF就会返回一个空对象。

在下面的例子中,我们可以反引用一个指向Person对象的引用。要注意的是,我们是从dummy表dual中取得引用值的。我们不需要指定对象表和检索条件,因为每个存放于对象表的对象都有唯一的互斥的对象标识,它是每一个指向对象的引用的一部分。

DECLARE
  p1      person;
  p_ref   REF  person;
  NAME    VARCHAR2 (15);
BEGIN
  ...
  /* Assume that p_ref holds a valid reference
  to an object stored in an object table. */

  SELECT  DEREF(p_ref)
    INTO  p1
    FROM  DUAL;

  NAME    := p1.last_name;
END ;

我们可以在后续的SQL语句中用DEREF进行反引用操作,如下例所示:

CREATE  TYPE  personref AS  OBJECT(
  p_ref   REF  person
)
/

DECLARE
  NAME     VARCHAR2 (15);
  pr_ref   REF  personref;
  pr       personref;
  p        person;
BEGIN
  ...
  /* Assume pr_ref holds a valid reference. */
  SELECT  DEREF(pr_ref)
    INTO  pr
    FROM  DUAL;

  SELECT  DEREF(pr.p_ref)
    INTO  p
    FROM  DUAL;
  ...
END ;
/

下面是一个我们不能在过程语句中使用DEREF函数的例子:

BEGIN
  ...
  p1 := DEREF(p_ref);   -- not allowed

在SQL语句中,我们可以使用点标志通过一个对象字段来引用它的属性,也可以通过一个对象字段的属性引用另一个属性。如果使用了表别名,那么就还能通过引用字段来访问属性。例如,下面的语法就是有效的:

table_alias.object_column.ref_attribute
table_alias.object_column.ref_attribute.attribute
table_alias.ref_column.attribute

假设我们在SQL*Plus中运行下面的脚本来创建对象类型Address和Person,对象表persons:

CREATE  TYPE  address AS  OBJECT(
  street     VARCHAR2 (35),
  city       VARCHAR2 (15),
  state      CHAR (2),
  zip_code   INTEGER
)
/

CREATE  TYPE  person AS  OBJECT(
  first_name     VARCHAR2 (15),
  last_name      VARCHAR2 (15),
  birthday       DATE ,
  home_address   REF  address,   -- shared with other Person objects
  phone_number   VARCHAR2 (15)
)
/

CREATE    TABLE  persons OF  person
/

引用属性home_address对应对象表persons中的一个引用,该引用指向存放在其他表中的Address对象的字段。填充数据表之后,我们就可以像下面这样反引用它的引用来得到特定的address:

DECLARE
  addr1 Address;
  addr2 Address;
  ...
BEGIN
  SELECT  DEREF(home_address)
    INTO  addr1
    FROM  persons p
   WHERE  p.last_name = 'Derringer' ;
END ;

在下面的例子中,我们可以通过引用字段home_address来找到属性street。这种情况下,我们必须要使用表别名。

DECLARE
  my_street   VARCHAR2 (25);
  ...
BEGIN
  SELECT  p.home_address.street
    INTO  my_street
    FROM  persons p
   WHERE  p.last_name = 'Lucas' ;
END ;

2、插入对象

我们可以使用insert语句为对象表添加一条记录。下例中,我们向对象表persons插入一个Person对象:

BEGIN
  INSERT  INTO  persons
       VALUES  ('Jenifer''Lapidus' , ...);
END ;

另外,我们还可以使用对象类型Person的构造函数来插入记录:

BEGIN
  INSERT  INTO  persons
       VALUES  (person('Albert''Brooker' , ...));
END ;

下例中,我们可以使用RETURNING子句把对象Person的引用保存在本地变量中。注意一下这个子句是如何模拟SELECT语句的。我们也可以在UPDATE和DELETE语句中使用RETURNING子句。

DECLARE
  p1_ref   REF  person;
  p2_ref   REF  person;
BEGIN
  INSERT  INTO  persons p
       VALUES  (Person('Paul''Chang' , ...))
    RETURNING REF (p)
         INTO  p1_ref;

  INSERT  INTO  persons p
       VALUES  (Person('Ana''Thorne' , ...))
    RETURNING REF (p)
         INTO  p2_ref;
END ;

要往对象表中插入对象,我们还可以利用返回同样对象类型的子查询来进行操作。示例如下:

BEGIN
  INSERT  INTO  persons2
    SELECT  VALUE(p)
      FROM  persons p
     WHERE  p.last_name LIKE  '%Jones' ;
END ;

拷贝到对象表person2的行被赋予新的对象标识。对象标识是不会从对象表persons中拷贝出来的。

下面的脚本创建一个名为department的关系表,其中有一个类型为Person的字段,然后向表中插入一条记录。注意如何使用构造函数Person()为字段manager提供值。

CREATE  TABLE  department (
  dept_name VARCHAR2 (20),
  manager person,
  LOCATION VARCHAR2 (20))
/
INSERT  INTO  department
     VALUES  ('Payroll' , Person('Alan''Tsai' , ...), 'Los Angeles' )
/

存放到字段manager中的新Person对象是不能被引用的,因为它是被存放在字段中(不是行中)的,也就没有对象标识。

3、更新对象

如果要修改对象表中的对象属性,我们可以像下面这样使用UPDATE语句:

BEGIN
  UPDATE  persons p
     SET  p.home_address = '341 Oakdene Ave'
   WHERE  p.last_name = 'Brody' ;

  UPDATE  persons p
     SET  p = person('Beth''Steinberg' , ...)
   WHERE  p.last_name = 'steinway' ;
END ;

4、删除对象

我们可以用DELETE语句从对象表中删除对象。要有选择的删除对象,我们就得在WHERE子句中进行指定:

BEGIN
  DELETE  FROM  persons p
        WHERE  p.home_address = '108 Palm Dr' ;
END ;

分享到:
评论

相关推荐

    PLSQL Developer用户指南

    4 PL/SQL Developer 7.0 用户指南 6.6 更新数据库 .......43 6.7 查看和编辑 XMLTYPE 列 .........44 6.8 直接查询导出 .....44 6.9 保存 SQL 脚本 .....44 6.10 创建标准查询 .....45 7. 命令窗口.......46 7.1 ...

    pl/sql操作手册

    4 PL/SQL Developer 7.0 用户指南 6.6 更新数据库....................................................43 6.7 查看和编辑 XMLTYPE 列..........................................44 6.8 直接查询导出................

    精通Oracle.10g.PLSQL编程

    PUSQL基础 3.1 PL/SQL块简介 3.1.1 PL/SQL块结构 3.1.2 PL/SQL块分类 3.2 定义并使用变量 3.2.1 标量变量 3.2.2 复合变量 3.2.3 参照变量 3.2.4 LOB变量 3.2.5 非PL...

    Oracle_Database_11g完全参考手册.part2/3

    《Oracle Database 11g完全参考手册》全面详细地介绍了Oracle Database 11g的强大功能,阐述了如何使用所有的新增功能和工具,如何执行功能强大的SOL查询,如何编写PL/SQL和SQL*Plus语句,如何使用大对象和对象,...

    Oracle_Database_11g完全参考手册.part3/3

    《Oracle Database 11g完全参考手册》全面详细地介绍了Oracle Database 11g的强大功能,阐述了如何使用所有的新增功能和工具,如何执行功能强大的SOL查询,如何编写PL/SQL和SQL*Plus语句,如何使用大对象和对象,...

    数据库基础

    §11.2 SQL与PL/SQL 231 §11.2.1 什么是PL/SQL? 231 §11.2.1 PL/SQL的好处 232 §11.2.1.1 有利于客户/服务器环境应用的运行 232 §11.2.1.2 适合于客户环境 232 §11.2.1.3 客户及服务器端的好处 232 §11.2.2 PL...

    OCPOCA认证考试指南全册:Oracle Database 11g(1Z0-051,1Z0-052,1Z0-053)--详细书签版(第1/2部分)

    8.3.1 存储的与匿名的PL/SQL程序块 282 8.3.2 PL/SQL对象 282 8.4 监视和解决锁定冲突 286 8.4.1 共享锁与排他锁 287 8.4.2 排队机制 287 8.4.3 锁定争用 288 8.4.4 死锁 290 8.5 撤销概述 291 8.6 事务与...

    Oracle8i_9i数据库基础

    §11.2 SQL与PL/SQL 231 §11.2.1 什么是PL/SQL? 231 §11.2.1 PL/SQL的好处 232 §11.2.1.1 有利于客户/服务器环境应用的运行 232 §11.2.1.2 适合于客户环境 232 §11.2.1.3 客户及服务器端的好处 232 §11.2.2 PL...

    Linux环境数据库管理员指南

    3.2.12 PL/SQL 43 3.2.13 模式 43 3.4 安装 43 3.4.1 安装前 44 3.4.2 安装Oracle 8 50 3.4.3 安装Oracle 8i 54 3.4.4 安装后 62 3.5 使用 Oracle 8/8i 65 3.5.1 启动和关闭 66 3.5.2 后台进程 67 3.5.3 创建帐号 ...

    PLSQL_Developer_9.0用户指南

    4 PL/SQL Developer 9.0 用户指南 7.8 直接查询导出 ......................................................... 45 7.9 保存 SQL 脚本 ........................................................ 45 7.10 创建...

    OCA认证考试指南(1Z0-052)

    10.2 识别和管理pl/sql对象 10.3 监视和解析锁定冲突 10.4 小结 10.5 本章测试题 第11章 管理撤销.. 11.1 解释撤销的作用 11.2 了解事务的撤销生成方式 11.3 管理撤销 11.4 小结 11.5 本章测试题...

    PLSQL_Developer7.0中文帮助手册

    4 PL/SQL Developer 7.0 用户指南 6.6 更新数据库............43 6.7 查看和编辑 XMLTYPE 列..44 6.8 直接查询导出..........44 6.9 保存 SQL 脚本..........44 6.10 创建标准查询..........45 7. 命令窗口............

    OCPOCA认证考试指南全册:Oracle Database 11g(1Z0-051,1Z0-052,1Z0-053)--详细书签版(第2/2部分)

    8.3.1 存储的与匿名的PL/SQL程序块 282 8.3.2 PL/SQL对象 282 8.4 监视和解决锁定冲突 286 8.4.1 共享锁与排他锁 287 8.4.2 排队机制 287 8.4.3 锁定争用 288 8.4.4 死锁 290 8.5 撤销概述 291 8.6 事务与...

    plsql中文使用说明

    4 PL/SQL Developer 7.0 用户指南 6.6 更新数据库....................................................43 6.7 查看和编辑 XMLTYPE 列..........................................44 6.8 直接查询导出................

    PLSQL中文手册(相当全面)

    4 PL/SQL Developer 7.0 用户指南 6.6 更新数据库....................................................43 6.7 查看和编辑 XMLTYPE 列..........................................44 6.8 直接查询导出................

    plsql developer 中文使用手册 最新 7.0 plsql developer 使用手册(中文)

    4 PL/SQL Developer 7.0 用户指南 6.6 更新数据库....................................................43 6.7 查看和编辑 XMLTYPE 列..........................................44 6.8 直接查询导出................

Global site tag (gtag.js) - Google Analytics