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

1.4.1.3 Native dynamic sql (nds)

Ever since Oracle 7.1, we PL/SQL developers have been able to use the built-in DBMS_SQL package to execute dynamic SQL and PL/SQL. This means that at runtime, you can construct the query, a DELETE TABLE, a CREATE TABLE, or even a PL/SQL block, as a string—and then execute it. Dynamic SQL is extremely handy when you are building ad hoc query systems, when you need to execute Data Definition Language (DDL) inside PL/SQL, and just generally when you don't know in advance exactly what you or the user will want to do. Dynamic SQL is a frequent requirement in web-based applications.

But there are some problems with DBMS_SQL; for example, it is a very complicated package; it only works with Oracle7 datatypes (no object types or INTERVALs need apply); and it is relatively slow.

So our dear friends at PL/SQL Central in Redwood Shores took pity on us all and re-implemented dynamic SQL directly in the PL/SQL language itself. This is called native dynamic SQL (NDS).

NDS introduces the EXECUTE IMMEDIATE statement to the PL/SQL language, and expands the OPEN FOR statement (for cursor variables) to support dynamic query strings to handle multi-row queries. The following function uses NDS to return the number of rows in whatever table you specify:

CREATE OR REPLACE FUNCTION tabCount (

tab IN VARCHAR2, whr IN VARCHAR2 := NULL)

RETURN INTEGER

IS

retval INTEGER;

BEGIN

EXECUTE IMMEDIATE

'SELECT COUNT(*)

FROM ' || tab ||

' WHERE ' || NVL (whr, '1=1')

INTO retval;

RETURN retval;

END;

Those of you familiar with DBMS_SQL will find this code a breath of fresh air. See Chapter 15 for extensive coverage of this wonderful new capability.

1.4.1.4 Bulk binds and collects

One of the major priorities of Oracle's PL/SQL development team is to speed up the performance of their language. This effort cannot come a moment too soon. We developers have been complaining about runtime performance for years, and finally the development team has responded (although, to be brutally honest, it seems to me that the intensive tuning steps taken in Oracle 8.0 were motivated at least partly by the need to make PL/SQL fast enough to support object types).

One area of improvement concerns the execution of bulk DML inside PL/SQL. Consider, for example, the following code that deletes each employee identified by the employee number found in the nested table list:

/* File on web: bulktiming.sql */

CREATE TYPE empnos_list_t IS VARRAY(100) OF NUMBER;

CREATE OR REPLACE PROCEDURE del_emps (list_in IN empnos_list_t)

IS

BEGIN

FOR listnum IN list_in.FIRST.. list_in.LAST

LOOP

DELETE FROM emp WHERE empno = list_in (listnum);

END LOOP;

END;

Easy to write, easy to read—but what about performance? Whenever this program issues its DELETE, a context switch takes place from PL/SQL to SQL to execute that command. If there are 100 elements in the list, there are at least 100 switches, with corresponding performance degradation.

Acknowledging this common requirement and its overhead, Oracle now offers a bulk bind variation on the FOR loop—the FORALL statement. With this statement, you can recode the del_emps procedure as follows:

CREATE OR REPLACE PROCEDURE del_emps (list_in IN empnos_list_t)

IS

BEGIN

FORALL listnum IN list_in.FIRST.. list_in.LAST

DELETE FROM emp WHERE empno = list_in (listnum);

END;

Now there will be many fewer context switches; all of the DELETE operations will be bundled into a single bulk operation and passed to the SQL layer together.

In addition to the FORALL bulk DML operator, Oracle 8.1 also offers the BULK COLLECT variation on the INTO clause of an implicit query. This operation allows you to retrieve multiple rows in a single context switch.

Chapter 13 gives you the inside scoop on FORALL, and BULK COLLECT is covered in Chapter 14.

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