Переключатели контекста Oracle SQL и PL / SQL - PullRequest
0 голосов
/ 26 апреля 2018

У меня есть код в oracle pl sql, хочу действительно хотеть понять, сколько там переключения контекста

If x=0 then 

  curserx= select a from mytable1;

Else

  curserx=select a from mytable1 where id=:x;

End;

Loop

  Fetch on cursorx

  Select c from mytable2 where a=curserx.a;

End loop;

Это просто пример кода, поэтому прошу прощения за любые ошибки в тексте и логическую ошибку.

1 Ответ

0 голосов
/ 26 апреля 2018

Я преобразовал ваш псевдокод в 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), эти два запроса будут работать с различными состояниями этих таблиц.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...