4、对象依赖性
f1 NUMBER,
f2 VARCHAR2(10),
f3 DATE
);
/
CREATE OR REPLACE TYPE Obj2 AS OBJECT (
f1 DATE,
f2 CHAR(1)
);
/
CREATE OR REPLACE TYPE Obj3 AS OBJECT (
a Obj1,
b Obj2
);
/
OBJ3依赖于OBJ1和OBJ2。所以删除或修改OBJ1或OBJ2之前没有首先删除OBJ3是非法的。
5、对象标识符和对象引用
对象标识符(object identifier ,简称为OID)是某种类型的永久对象的唯一定位符。与ROWID变量相类似(它唯一的标识了一行),对象标识符唯一标识了一个对象。
我们知道,REF CURSOR变量与CURSOR变量是不同的,它仅仅是指向一个游标的指针。对象引用也是一样。对象引用是一个指向对象的指针,而不是对象本身。在声明部分或表定义中声明对象引用的语法是:
Variable_name REF object_type;
这里Variable_name是对象引用的名字,而object_type是对象类型。
例如下面定义的ClassObj类型包含一个指向RoomObj的引用:
department CHAR(3),
course NUMBER(3),
description VARCHAR2(2000),
max_students NUMBER(3),
current_students NUMBER(3),
num_credits NUMBER(1),
room REF RoomObj
);
/
6、在DML语句中使用对象
1)INSERT
在需要使用对象的INSERT 语句中, 你可以使用对象构造函数,或者一个对象的PL/SQL变量,它们都包含了要插入的对象。对于INSERT语句而言,对象的行为方式和标量类型是很相似的。
2)UPDATE
在UPDATE语句中的WHERE或VALUES子句中,对象可以被用作联编变量。
下面的块创建了一个新的房间,并更新classes表以反映新插入的数值。
v_NewRoom RoomObj :=
RoomObj(99990, 'Building 7', 200, 50, 'Discussion Room F');
v_RoomRef REF RoomObj;
BEGIN
-- The RETURNING clause on this statement puts a reference to the
-- newly inserted room into v_RoomRef.
INSERT INTO rooms r VALUES (v_NewRoom)
RETURNING REF(r) INTO v_RoomRef;
UPDATE classes
SET room = v_RoomRef
WHERE department = 'NUT' and course = 307;
END;
/
3)DELETE
类似地,DELETE语句可以在WHERE子句中引用对象或者对象属性。例如,下面的DELETE语句将删除所有主修为历史的学生
WHERE s.student.major=’History’;
4)SELECT语句中的列对象
如果对象作为表中的列对象进行存储,那么你可以使用标准的SELECT语句对它直接进行检索,如下面的例子所示
DECLARE
v_Student StudentObj;
v_Address AddressObj;
CURSOR c_Students IS
SELECT student, address
FROM students;
BEGIN
-- Print out the ID's of all students.
OPEN c_Students;
LOOP
FETCH c_Students INTO v_Student, v_Address;
EXIT WHEN c_Students%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Student ID: ' || v_Student.ID);
END LOOP;
CLOSE c_Students;
END;
/
你可以在WHERE子句中引用一个列对象,只要该对象是确实有效的。
例如,下面的SELECT语句时合法的,因为使用了完全路径引用它的ID属性:
FROM students
WHERE students.student.id=10009;
但是,在PL/SQL中你不能使用相同的语句,因为该表没有使用别名。下面的块将引发错误“PLS-327:students is not in SQL scope here”
v_Student StudentObj;
BEGIN
-- Raises PLS-327
SELECT student
INTO v_Student
FROM students
WHERE students.student.ID = 10009;
END;
/
--这个问题的解决办法是使用表别名
DECLARE
v_Student StudentObj;
BEGIN
-- Succeeds, because of the table alias
SELECT student
INTO v_Student
FROM students s
WHERE s.student.ID = 10009;
END;
/
提示:当从包含列对象或者行对象的表中执行选择操作时请一定使用表别名。这种方式可以确保该查询在SQL和PL/SQL中都能正常工作。
5)SELECT语句中的行对象
VALUE运算符
VALUE返回一个对象,而不是属性列表。它接受“相关变量”作为参数。此时,相关变量仅仅是一个表别名。下面的例子说明了VALUE的使用方法。
v_RoomID rooms.id%TYPE;
v_Building rooms.building%TYPE;
v_RoomNumber rooms.room_number%TYPE;
v_NumberSeats rooms.number_seats%TYPE;
v_Description rooms.description%TYPE;
v_RoomObj RoomObj;
BEGIN
-- SELECT without using VALUE. This is just like a relational
-- query.
SELECT *
INTO v_RoomID, v_Building, v_RoomNumber, v_NumberSeats, v_Description
FROM rooms r
WHERE ID = 99993;
-- SELECT using VALUE. In this case, we retrieve a RoomObj.
SELECT VALUE(r)
INTO v_RoomObj
FROM rooms r
WHERE ID = 99993;
END;
/
返回VALUE的查询的结果集是对象,而不是一组属性。
REF运算符
REF运算符将返回一个指向该查询对象的REF变量,而不是对象本身。和VALUE很类似,REF接受一个相关变量作为参数。
DEREF运算符
有了一个引用以后,DEREF将返回原先的对象。
下面这个例子说明了REF和DEREF的使用方法
v_RoomRef REF RoomObj;
v_Room RoomObj;
BEGIN
-- Select a reference to the room, not the room itself.
SELECT REF(r)
INTO v_RoomRef
FROM rooms r
WHERE ID = 99993;
-- Dereference v_RoomRef to get an object, and update it.
-- This will return a local object, which is not the same
-- as the object stored in the rooms table.
SELECT DEREF(v_RoomRef)
INTO v_Room
FROM dual;
-- This updates the local object.
v_Room.room_number := 201;
END;
/
悬挂REF
当一个REF变量指向的对象被删除了,那么该REF就处于“悬挂状态”,因为它现在指向了一个不存在的对象。对于悬挂REF变量执行DEREF是非法的。但是你可以使用IS DANGLING谓词检查它是否处于悬挂状态。
--set all dangling REFs to NULL
UPDATE classes
SET room=NULL
WHERE room IS DANGLING;
END;
注意:所有上述这些运算符(VALUE,REF,DEREF以及IS DANGLING)只能在SQL语句中使用,不能在过程性语句中使用。
6)RETURNING 子句
ORACLE为INSERT 和UPDATE语句提供了一个新的子句。RETURNING可以用来从新插入的行或者新更新的行中检索信息,而不必进行其他的查询操作。语法如下:
RETURNING select_list INTO into_list;
例如,如果你正在向一个对象表中插入一个对象,你可以使用下述语句得到指向新插入对象的引用
v_ClassRef REF ClassObj;
BEGIN
INSERT INTO CLASSES c VALUES
(ClassObj('HIS', 101, 'History 101', 30, 0, 4, NULL))
RETURNING REF(c) INTO v_ClassRef;
END;