Читать «Язык PL/SQL» онлайн - страница 90

Иван Сергеевич Задворьев

13 DBMS_OUTPUT.PUT_LINE(SQLERRM);

14 END;

15

16 BEGIN

17 EXECUTE IMMEDIATE l_sql_text INTO l_tab1 USING 3;

18 EXCEPTION

19 WHEN OTHERS THEN

20 DBMS_OUTPUT.PUT_LINE(SQLERRM);

21 END;

22

23 END;

24 /

Отобранная строка: 2B

ORA-01422: exact fetch returns more than requested number of rows

ORA-01403: no data found

PL/SQL procedure successfully completed.

Рассмотрим еще два примера использования NDS.

Пусть база данных спроектирована таким образом, что у каждой таблицы столбец первичного ключа называется id и имеет тип INTEGER.

Напишем процедуру, которая удаляет строку в любой таблице по значению ее первичного ключа. Параметрами процедуры будут имя таблицы и значение столбца id удаляемой строки.

CREATE TABLE tab1(id INTEGER PRIMARY KEY,at1 CHAR(1));

INSERT INTO tab1 VALUES(1,'a');

INSERT INTO tab1 VALUES(2,'b');

CREATE TABLE tab2(id INTEGER PRIMARY KEY,at1 CHAR(1));

INSERT INTO tab2 VALUES(20,'x');

INSERT INTO tab2 VALUES(30,'y');

SQL> CREATE OR REPLACE PROCEDURE delete_by_id (p_table_name IN VARCHAR2,

2 p_id IN INTEGER) IS

3 BEGIN

4 EXECUTE IMMEDIATE 'DELETE FROM '||p_table_name||' WHERE id=:p_id'

5 USING p_id;

6 DBMS_OUTPUT.PUT_LINE('In table '||p_table_name||' '

7 ||SQL%ROWCOUNT||' rows deleted');

8 END;

9 /

Procedure created.

SQL> set serveroutput on

SQL> EXECUTE delete_by_id('tab1',1);

In table tab1 1 rows deleted

PL/SQL procedure successfully completed.

SQL> EXECUTE delete_by_id('tab1',-1);

In table tab1 0 rows deleted

PL/SQL procedure successfully completed.

SQL> EXECUTE delete_by_id('tab2',20);

In table tab2 1 rows deleted

PL/SQL procedure successfully completed.

Для NDS в PL/SQL поддерживаются средства массовой обработки данных (bulk processing). Конструкция BULK COLLECT указывается в том случае, когда известно, что SQL-запрос может иметь в результирующей выборке не одну, а несколько строк. Тогда переменной, в которую помещается результирующая выборка, должна быть коллекция, то есть и здесь прослеживается аналогия с командой SELECT INTO для статических предложений SQL. Также команда EXECUTE IMMEDIATE может использоваться совместно с рассматриваемой ранее командой FORALL.

Вернем содержимое таблиц tab1, tab2 в исходное состояние и создадим теперь процедуру print_id_list со считыванием в коллекцию всех строк результирующей выборки с помощью конструкции BULK COLLECT.

SQL> CREATE OR REPLACE PROCEDURE print_id_list(p_table_name IN VARCHAR2,

2 p_id IN INTEGER) IS

3 TYPE t_table IS TABLE OF INTEGER;

4 l_table t_table;

5 BEGIN

6 EXECUTE IMMEDIATE 'SELECT id FROM '||p_table_name||' WHERE id>:p_id'

7 BULK COLLECT INTO l_table

8 USING p_id;

9 FOR i IN 1..l_table.COUNT LOOP

10 DBMS_OUTPUT.PUT_LINE(l_table(i));

11 END LOOP;

12 END;

13 /

Procedure created.

SQL> EXECUTE print_id_list('tab1',0);

1

2

PL/SQL procedure successfully completed.

SQL> EXECUTE print_id_list('tab2',20);

30

PL/SQL procedure successfully completed.

Как видно, использование NDS позволяет писать очень компактный код.

Пакет DBMS_SQL

Использование встроенного пакета DBMS_SQL для выполнения динамического SQL предусматривает в общем случае последовательность из 8 этапов.