Рекурсивным вызовом называется вызов подпрограммы из тела этой же подпрограммы.
При каждом рекурсивном вызове:
создается новый экземпляр всех элементов, объявленных в подпрограмме, включая параметры, переменные, курсоры и исключения;
создается свой экземпляр SQL-оператора.
Рассмотрим в качестве примера рекурсивных вызовов создание последовательности Фибоначчи (1, 1, 2, 3, 5, 8, 13, 21, ...), в которой каждый следующий элемент является суммой двух предыдущих.
Следующая функция fibonati1 реализует формирование последовательности Фибоначчи с применением рекурсии:
FUNCTION fibonati1 (n POSITIVE) RETURN INTEGER IS BEGIN IF (n = 1) OR (n = 2) THEN RETURN 1; ELSE RETURN fibonati1 (n-1) + fibonati1 (n-2); END IF; END fibonati1;
Вместо рекурсивного способа можно использовать и итерационный способ, который менее нагляден, но требует и меньше памяти и быстрее выполняется.
Так, следующая функция fibonati2 реализует формирование последовательности Фибоначчи итерационным способом:
FUNCTION fibonati2 (n POSITIVE) RETURN INTEGER IS pos1 INTEGER := 1; pos2 INTEGER := 0; sum INTEGER; BEGIN IF (n = 1) OR (n = 2) THEN RETURN 1; ELSE sum := pos1 + pos2; FOR i IN 3..n LOOP pos2 := pos1; pos1 := sum; sum := pos1 + pos2; END LOOP; RETURN sum; END IF; END fibonati2;
Язык PL/SQL позволяет реализовывать взаимно рекурсивные вызовы, при которых подпрограммы прямо или опосредованно вызывают друг друга.
Внешние процедуры
Использование внешних процедур значительно расширяет функциональность сервера, предоставляя интерфейс для вызова программ, разработанных на других языках программирования, таких как C++ или Pascal, и созданных как DLL-библиотеки.
Во время выполнения блока PL/SQL динамически загружается DLL-библиотека и происходит вызов внешней процедуры как подпрограммы PL/SQL. Внешние процедуры всегда выполняются в отдельном процессе.
Вызовы внешних процедур можно выполнять из:
анонимных блоков PL/SQL;
методов, объявленных в объектном типе;
хранимых или пакетных подпрограмм;
триггеров базы данных;
SQL-операторов, вызываемых только для пакетных подпрограмм.
Для применения внешней процедуры следует сначала определить используемую DLL-библиотеку, выполнив оператор CREATE LIBRARY library_name {IS | AS} 'file_path';. Затем необходимо зарегистрировать внешнюю процедуру, указав в процедуре PL/SQL, используемой для опосредованного вызова внешней процедуры, место расположения процедуры, способ ее вызова и список передаваемых параметров.
Если DLL-библиотека c_lib.dll содержит функцию f1_ext, которая определена в С как int c_ext_f1(int x_val, int y_val);, то подпрограмма PL/SQL reg_ext_f1, выполняющая регистрацию этой внешней процедуры, может быть записана следующим образом:
CREATE FUNCTION reg_ext_f1( x BINARY_INTEGER, y BINARY_INTEGER) RETURN BINARY_INTEGER AS EXTERNAL LIBRARY c_lib NAME "c_ext_f1" -- Имя внешней функции LANGUAGE C;
Для вызова внешней функции DLL-библиотеки из анонимного блока PL/SQL достаточно выполнить вызов функции PL/SQL, зарегистрированной как внешняя функция.
Например:
DECLARE var1 BINARY_INTEGER; x BINARY_INTEGER; y BINARY_INTEGER; BEGIN x:=1; y:=2; -- Вызов внешней функции f1_ext: var1 := reg_ext_f1(x, y); END;