对象类型

对象类型的创建和删除

创建格式:

create type typename as object
(attrname datatype...); -可选

例如:

create type name_t as object(
    lname varchar(30),
    fname varchar(30),
    mi char(1)
);

可以看出,创建对象的语句和创建表很相似,除了不能指定主要键。

删除格式:

drop type typename;

删除之前需要注意的是,应该不存在其他的表或者对象类型依赖于要删除的这个类型,否则删除会失败。

对象类型的使用方法

对象类型有三种常见的用法:

  • 嵌套定义新类型的属性
  • 用于定义表的属性
  • 使用对象直接创建表(这个时候表的每一行都是一个该类型的对象实例)

各举一例进行说明:

- 嵌套定义
create type person_t as object(
    ssno int,
    pname name_t, -使用了上一个例子里定义的对象类型
    age int
);

- 用于定义表的属性
create table teachers(
    tid int,
    tname name_t, -使用之前定义的对象类型作为表的属性
    room int
);

- 用对象创建表
create table people of person_t
(primary key(ssno)); - 这里可以选择性加上约束条件

对象值的创建,查询和更新

创建:通过对象构造函数,typename(argument,…)的格式进行创建对象。比如name_t(‘Einstein’, ‘Albert’, ‘E’); 通常可以配合insert将新对象直接放入表中。

查询:对于对象中的值,可以用点号自然的访问。

更新:可以修改整个对象,也可以直接对象内部成员变量的值。如果表本来就是对象类型构建的,还可以对整张表进行修改(配合筛选条件)。

对象的引用

定义引用关系和创建含引用关系的表

对于由对象类型创建出的表,系统会给他的每一个行对象分配一个唯一标识符,就类似内存地址。在别处可以直接通过引用这个标识符达到快速连接的作用。

声明这样的引用通过 REF object_type 来实现。

例如:

create type order_t as object(
    ordno int,
    cid char(4),
    aid char(3),
    pid char(3),
    qty int,
    dollars double precision,
    ordcust ref customer_t,
    ordagent ref agent_t,
    ordprod ref product_t
)

在用这个order_t对象类型再直接构建表的时候,对于对象类型中的引用,一定要用scope for (ref_name) is tablename的方法来限制这个引用的取值范围。

这个例子的总体上是这样的:

通过引用加入了别的表中的行对象,作为自己的属性。

引用关系查询

通过点访问就可以了。

要注意的是在含有引用的表格中,其实属性就是一个类似内存地址的行对象唯一标识符,可以进行大小比较和是否相等的判断。例如x1.ordcust < x2.ordcust是符合语法的,小于号前后的两个量本质上就是个唯一标识符,或者说指针、数字。

引用的函数与谓词

两个常用函数:

  • ref(),用来获得一个行对象的引用(指针或者说唯一标识符都行,理解成类似内存地址的东西)。
  • deref(),用来通过引用获得对象本身的内容。

可以说和C语言中的指针的逻辑非常相似。

两个谓词:

  • is dangling
  • is null

ref的其他约束

两张表之间相互引用关系的定义:

  1. 先部分创建第一个对象类,即只给出对象名而没有类型的详细定义。
  2. 再详细定义第二个对象类型,其中包含对第一个类型的引用属性。
  3. 详细定义第一个对象类型。
  4. 基于对象类型创建关系表。

相互引用的两张表的删除

  1. 先删除基于关系创建的表
  2. 强制删除对象类型(DROP TYPE type_name FROCE;)

ref属性数据的加载(输入)

  • 方法一:先不管ref属性的取值,之后再使用update进行修改,指定ref的指向。
  • 方法二:使用带有子查询的插入操作。即INSERT INTO table_name (子查询select…)

集合类型

Oracle的集合类型(书上叫做汇集类型)主要包括两种:(嵌套)表类型和数组类型。

表类型

例如:

create type dependents_t as table of person_t;
create table emloyees(
    eid int,
    eperson person_t,
    dependents dependents_t,
    primary key(eid)
)nested table dependents store as dependents_tab;

可见,要先创建表类型。然后在创建其他表(父级表)的时候最后要多一句嵌套表声明。这里声明了嵌套表dependents属性的行实际上都存在dependents_tab里面。但是这个dependents_tab只能通过父级表进行访问而不能直接访问。

一张表如果有属性是嵌套表,那这个表可以和他的嵌套表进行笛卡尔积。

使用嵌套游标的方法可以对父级表的每一行再加入一个循环处理这一行的嵌套表属性。

如果想要把嵌套表属性当做正常的表进行处理,一定要经过table()进行类型转换才行。

数组类型

例如:

create type extensions_t as varry(4) of int;
create table phonebook(
    phperson person_t,
    extensions extensions_t
);

同样可以通过table()将数组转化成表。

数组和嵌套表的区别有:

  • 嵌套表中行的排列是无序的,而数组的行排列是有序的。
  • 嵌套表中的最大数目无限制,但是数组的行最大数目是有限并且实现定义好的。
  • 嵌套表的行实际上储存在单独的存储表中(只能通过父级表访问),而数组则是直接存在包含数组属性的表中。
  • 对嵌套表可以insert和update,但是对数组只能一次整个改值(因为数组的地位就是一个属性)

过程SQL和PL/SQL

即用户自定义函数。不是重点。