Я преобразовал ваш псевдокод в PL / SQL и включил комментарии, указывающие, где, как я полагаю, у вас будет переключение контекста с механизма PL / SQL на механизм SQL.
Обратите внимание, что если вы запрашиваете нетривиальное количество строк, вы можете использовать FETCH BULK COLLECT INTO и извлекать несколько строк при каждой выборке, значительно уменьшая переключение контекста.
DECLARE
l_x_value INTEGER;
l_cursor SYS_REFCURSOR;
l_fetched mytble1.a%TYPE;
BEGIN
/* context switch to open */
IF x = 0
THEN
OPEN l_cursor FOR SELECT a FROM mytable1;
ELSE
OPEN l_cursor FOR
SELECT a
FROM mytable1
WHERE id = l_x_value;
END IF;
LOOP
/* context switch per fetch */
FETCH l_cursor INTO l_fetched;
EXIT WHEN l_cursor%NOTFOUND;
/* context switch for implicit cursor */
SELECT c
INTO l_fetched
FROM mytable2
WHERE a = curserx.a;
END LOOP;
/* context switch to close */
CLOSE l_cursor;
END;
Но это еще не все! Помните, что переключение контекста работает в обоих направлениях: SQL -> PL / SQL и PL / SQL -> SQL. Вы можете сократить накладные расходы при переходе от SQL к PL / SQL, объявив свою функцию с помощью прагмы UDF (12c +) или определив ее с помощью предложения WITH FUNCTION (также 12c +). Переключение контекста все еще существует, но некоторая работа выполняется во время компиляции, а не во время выполнения.
Таким образом, в приведенном ниже коде для каждого вызова функции из SELECT имеется переключатель.
CREATE OR REPLACE FUNCTION full_name (first_in IN VARCHAR2,
last_in IN VARCHAR2)
RETURN VARCHAR2
IS
BEGIN
RETURN first_in || ' ' || last_in;
END;
/
DECLARE
l_name VARCHAR2 (32767);
BEGIN
SELECT full_name (first_name, last_name) INTO l_name
FROM employees
WHERE employee_id = 100;
DBMS_OUTPUT.PUT_LINE (l_name);
END;
/
Наконец, предостережение: вы должны сделать все возможное, чтобы избежать выполнения SQL внутри функции, которая затем вызывается из SQL. Стандартная модель согласованности чтения, которая работает для вашего оператора SQL, не будет "перенесена" в SQL функции. Другими словами, если ваш «внешний» SELECT запускается в 10:00 и работает в течение часа, а в 10:05 кто-то удаляет строки из таблицы, которая используется как во внешнем запросе, так и в запросе в функции (и commit), эти два запроса будут работать с различными состояниями этих таблиц.