Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming PL SQL.doc
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
5.06 Mб
Скачать

21.2.5.2 The reftohex function

Earlier, I used the following query to show you the underlyinghex value of a REF:

SELECT REF(c) FROM catalog_items c WHERE ROWNUM = 1;

The results of this query were displayed in hexadecimal because SQL*Plus knows how to convert the binary data of a REF to a printed hexadecimal form. You can explicitly specify that same conversion using the built-in REFTOHEX function, as follows:

SELECT REFTOHEX(REF(c)) FROM catalog_items c WHERE ROWNUM = 1;

If you're executing a query from SQL*Plus, using REFTOHEX is just so much extra typing. However, if you are executing a query from within PL/SQL and you want to return the hexadecimal value of a REF, you can use REFTOHEX in your SQL query to make your intentions, and the resulting conversion, explicit.

It would be ideal if REFTOHEX could also be invoked directly from PL/SQL. For example, the following code retrieves a REF from the database (itemref) and attempts to use REFTOHEX to convert that REF into its hexadecimal representation:

DECLARE

itemref REF catalog_item_t;

itemref_as_hex VARCHAR2(100);

BEGIN

-- Retrieve a REF value from the database

SELECT REF(c) INTO itemref

FROM catalog_items c WHERE ROWNUM = 1;

-- Use REFTOHEX to get the hexadecimal representation of the REF value

itemref_as_hex := REFTOHEX(itemref);

--Display the length of the result, and the result itself.

DBMS_OUTPUT.PUT_LINE(LENGTH(itemref_as_hex));

DBMS_OUTPUT.PUT_LINE(itemref_as_hex);

END;

Unfortunately, this piece of code doesn't work. Try it, and you'll get the following results:

ERROR at line 10:

ORA-06550: line 10, column 22:

PLS-00201: identifier 'REFTOHEX' must be declared

ORA-06550: line 10, column 4:

PL/SQL: Statement ignored

This message footprint indicates that PL/SQL can't always perform the same functions as SQL. Even though Oracle9i advertises a single parser shared by PL/SQL and SQL, support for REFTOHEX obviously requires something deeper than parsing. I doubt that there is any need to retrieve additional data from the database to convert from a REF to a hexadecimal value, so I would expect support for this particular function from PL/SQL. It would be great if application developers didn't face surprises like this one, but Oracle has added support in PL/SQL for a number of other built-in functions (like NVL2 and TREAT), so at least the trend is in the right direction.

21.2.5.3 The utl_ref package

The UTL_REF built-in package performs the dereferencing operation without an explicit SQL call, allowing your application to perform a programmatic lock, select, update, or delete of an object given only its REF. As a short example, I can add a method such as the following to the subject_t type:

MEMBER FUNCTION print_bt (str IN VARCHAR2)

RETURN VARCHAR2

IS

bt subject_t;

BEGIN

IF SELF.broader_term_ref IS NULL

THEN

RETURN str;

ELSE

UTL_REF.SELECT_OBJECT(SELF.broader_term_ref, bt);

RETURN bt.print_bt(NVL(str,SELF.name)) || ' (' || bt.name || ')';

END IF;

END;

This recursive procedure walks the hierarchy from the current subject to the "topmost" broader subject.

In C, Better Support for REFs

While PL/SQL offers few overwhelming reasons to program with object references, you would find more benefits to this programming style with the Oracle Call Interface (OCI), Oracle's C/C++ language interface, or even with Pro*C. In addition to the ability to navigate REFs, similar to what you find in PL/SQL, OCI provides complex object retrieval (COR). With COR, you can retrieve an object and all its REFerenced neighbors in a single call. Both OCI and Pro*C support a client-side object cache, allowing an application to load objects into client memory and to manipulate (select, insert, update, delete) them as if they were in the database. Then, in a single call, the application can flush all the changes back to the server. In addition to improving the programmer's functional repertoire, these features reduce the number of network round trips, improving overall performance.

When using the procedures in UTL_REF, the REF argument you supply must be typed to match your object argument. The complete list of subprograms in UTL_REF follows:

UTL_REF.SELECT_OBJECT ( obj_ref IN, object_variable OUT);

Finds the object to which obj_ref points and retrieves a copy in object_variable.

UTL_REF.SELECT_OBJECT_WITH_CR ( obj_ref IN, object_variable OUT);

Like SELECT_OBJECT, but makes a copy ("snapshot") of the object. This version exists to avoid a mutating table error (ORA-4091), which can occur if you are updating an object table and setting the value to a function, but the function uses UTL_REF to dereference an object from the same table you're updating.

UTL_REF.LOCK_OBJECT ( obj_ref IN);

Locks the object to which obj_ref points but does not fetch it yet.

UTL_REF.LOCK_OBJECT ( obj_ref IN, object_variable OUT);

Locks the object to which obj_ref points and retrieves a copy in object_variable.

UTL_REF.UPDATE_OBJECT ( obj_ref IN, object_variable IN);

Replaces the object to which obj_ref points with the value supplied in object_variable. This operation updates all of the columns in the corresponding object table.

UTL_REF.DELETE_OBJECT ( obj_ref IN);

Deletes the object to which obj_ref points.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]