Oracle оптимизирует запросы, избегая курсоров

Я работаю над куском sql, который я хочу оптимизировать. У меня внутри куча курсоров. Мне интересно, могу ли я использовать что-то еще вместо курсоров. Я думаю, используя какие-то переменные, заполняя их, и для остальной части лечения избегая соединения с БД (у меня комплексное лечение).

Например, у меня есть кусок кода, как:

TYPE rec_basket IS RECORD (
 FIELD1 VARCHAR2(40),
 FIELD2 NUMBER(10),
 FIELD3 VARCHAR2(6)
 );

 TYPE tab_basket IS TABLE OF rec_basket
 INDEX BY BINARY_INTEGER;

........................

CURSOR cur_baskets
   IS
select * from toto

............................

 FOR i IN cur_baskets
   LOOP
  l_tab_basket (l_nbasket).field1 := i.field1;
  l_tab_basket (l_nbasket).field2 := i.field2;
  l_tab_basket (l_nbasket).field3  := i.field3;
  l_nbasket := l_nbasket + 1;    
   END LOOP;

Использование курсора и заполнение переменной l_tab_basket - лучший путь? Я использую l_tab_basket (index) где-то в моем коде. Причина, по которой я поместил этот фрагмент кода, заключается в том, что я хотел бы использовать этот механизм для других моих курсоров. На самом деле у меня есть курсор внутри другого. И для каждой линии каждого из них у меня есть какое-то лечение. Я хотел бы заменить курсоры на что-то еще, но я не знаю как. Благодарю.

2 ответа

Решение

Логика вашего кода не очень понятна. Вы не написали всю программу. Давайте рассмотрим:

CURSOR cur_baskets IS выбрать * с toto

Здесь значение считывается из таблицы toto и помещается в курсор.

В следующих строках значения считываются из курсора и помещаются в l_tab_basket.

FOR i IN cur_baskets LOOP l_tab_basket (l_nbasket).field1: = i.field1; l_tab_basket (l_nbasket).field2: = i.field2; l_tab_basket (l_nbasket).field3: = i.field3; l_nbasket: = l_nbasket + 1;
КОНЕЦ ЦИКЛА;

Так что одни и те же значения собираются в локальной переменной дважды. Этого можно избежать. Вы можете найти способы прямой вставки или обновления целевой таблицы.

Вы можете попробовать массовый сбор. Если toto мало, вы можете вставить или обновить целевую таблицу без использования курсора.

Вы можете использовать BULK COLLECT для извлечения всех записей во вложенную таблицу. Это будет работать в 10g+:

SQL> DECLARE
  2     TYPE rec_basket IS RECORD(
  3        field1 VARCHAR2(40),
  4        field2 NUMBER(10),
  5        field3 VARCHAR2(6));
  6     TYPE tab_basket IS TABLE OF rec_basket INDEX BY BINARY_INTEGER;
  7     l_tab_basket tab_basket;
  8  BEGIN
  9     SELECT 'a', ROWNUM, 'b'
 10       BULK COLLECT INTO l_tab_basket
 11       FROM dual CONNECT BY LEVEL <= 1000;
 12  END;
 13  /

PL/SQL procedure successfully completed

Имейте в виду, что Oracle 10g автоматически извлекает записи из неявных курсоров навалом (100) в pl/sql, поэтому выигрыш в лучшем случае должен быть минимальным: вы, вероятно, потратите больше времени на запросы к БД, чем на построение массива, если массив действительно не является действительно большой (и в этом случае целесообразно использовать вложенную таблицу?)

Другие вопросы по тегам