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

13.1.3 Returning Information from dml Statements

Suppose that I perform an UPDATE or DELETE, and then need to get information about the results of that statement for future processing. Rather than perform a distinct query following the DML statement, I can add a RETURNING clause to an INSERT, UPDATE, or DELETE and retrieve that information directly into variables in my program. With the RETURNING clause, you can reduce network round trips, consume less server CPU time, and minimize the number of cursors opened and managed in the application.

Here are some examples that demonstrate the capabilities of this feature.

  • The following very simple block shows how I use the RETURNING clause to retrieve a value (the new salary) that was computed within the UPDATE statement:

  • DECLARE

  • myname employee.last_name%TYPE;

  • mysal employee.salary%TYPE;

  • BEGIN

  • FOR rec IN (SELECT *

  • FROM employee)

  • LOOP

  • UPDATE employee

  • SET salary = new_compensation (rec)

  • WHERE employee_id = rec.employee_id

  • RETURNING salary, last_name

  • INTO mysal, myname;

  • DBMS_OUTPUT.PUT_LINE ('New salary for ' ||

  • myname || ' = ' || mysal;

  • END LOOP;

END;

  • In the following block, I take advantage of RETURNING to obtain a LOB locator so that I can move the contents of a BFILE image into a BLOB in the database:

  • DECLARE

  • pic_file BFILE := BFILENAME('WEB_PIX', 'memories.jpg');

  • pic_blob_loc BLOB := EMPTY_BLOB( );

  • BEGIN

  • INSERT INTO web_graphic_blobs

  • VALUES (1, pic_blob_loc)

  • RETURNING image INTO pic_blob_loc;

  • DBMS_LOB.FILEOPEN(pic_file, DBMS_LOB.FILE_READONLY);

  • DBMS_LOB.LOADFROMFILE(dest_lob => pic_blob_loc,

  • src_lob => pic_file,

  • amount => DBMS_LOB.GETLENGTH(pic_file));

  • DBMS_LOB.FILECLOSE(pic_file);

  • END;

/

  • Suppose that I perform an UPDATE that modifies more than one row. In this case, I can return information not just into a single variable, but into a collection using the BULK COLLECT syntax. This technique is shown below in a FORALL statement:

  • DECLARE

  • names name_varray;

  • new_salaries number_varray;

  • BEGIN

  • populate_names_array (names);

  • FORALL indx IN names.FIRST .. names.LAST

  • UPDATE compensation

  • SET salary = new_compensation (names(indx))

  • WHERE name = names (indx)

  • RETURNING salary BULK COLLECT INTO new_salaries;

  • ...

END;

13.1.4 Dml and Exception Handling

When an exception occurs in a PL/SQL block, Oracle does not roll back any of the changes made by DML statements in that block. It is up to you, the manager of the application's logical transaction, to decide what sort of behavior should occur.

Consider the following procedure:

CREATE OR REPLACE PROCEDURE empty_library (

pre_empty_count OUT PLS_INTEGER)

IS

BEGIN

-- The tabCount function returns the number

-- of rows in the specified table, using

-- Native Dynamic SQL. See Chapter 15 for details.

pre_empty_count := tabcount ('books');

DELETE FROM books;

RAISE NO_DATA_FOUND;

END;

Notice that I set the value of the OUT parameter before I raise the exception. Now let's run an anonymous block that calls this procedure, and examine the after-effects:

DECLARE

table_count NUMBER := -1;

BEGIN

INSERT INTO books

VALUES (...);

empty_library (table_count);

EXCEPTION

WHEN OTHERS

THEN

DBMS_OUTPUT.put_line (tabcount ('books'));

DBMS_OUTPUT.put_line (table_count);

END;

The output is:

0

-1

Notice that my rows remain deleted from the books table even though an exception was raised; Oracle did not perform an automatic rollback. My table_count variable, however, retains its original value. Oracle does perform a kind of rollback on the program variables involved when an exception occurs.

So it is up to you to perform rollbacks—or rather, to decide if you want to perform a rollback—in programs that perform DML. Here are some things to keep in mind in this regard:

  • If your block is an autonomous transaction (described later in this chapter), then you must perform a rollback or commit (usually a rollback) when an exception is raised.

  • You can use savepoints to control the scope of a rollback. In other words, you can roll back to a particular savepoint and thereby preserve a portion of the changes made in your session. Savepoints are also explored later in this chapter.

  • If an exception propagates past the outermost block (i.e., it goes "unhandled"), then in most host execution environments for PL/SQL like SQL*Plus, an unqualified rollback is automatically executed, reversing any outstanding changes.

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