Разница между FETCH/FOR для цикла курсора в PL / SQL

Я знаю, что выборка курсора даст мне доступ к переменным, таким как %ROWCOUNT, %ROWTYPE, %FOUND, %NOTFOUND, %ISOPEN

...но мне было интересно, есть ли другие причины использовать

Open-Fetch-закрыть инструкции для цикла курсора

, а не

цикл курсора с циклом FOR... (На мой взгляд, это лучше, потому что это просто)

Что вы думаете?

4 ответов


с точки зрения производительности, разница намного сложнее, чем Тим Холл совет, что OMG пони связаны с предполагает. Я считаю, что этот совет является введением к большему разделу, который был взят для интернета - я ожидаю, что Тим сделал большинство, если не все из этих моментов в книге. Кроме того, все это обсуждение зависит от используемой версии Oracle. Я считаю, что это правильно для 10.2, 11.1, и 11.2, но есть определенно различия, если вы начнете возвращаться к старым выпускам.

конкретный пример в подсказке, прежде всего, довольно нереалистичен. Я никогда не видел, чтобы кто-то кодировал однорядную выборку, используя явный курсор, а не SELECT INTO. Поэтому тот факт, что SELECT INTO более эффективен, имеет очень ограниченное практическое значение. Если мы обсуждаем циклы, то нас интересует, насколько дорого стоит получение многих строк. И вот тут-то и начинаются сложности. в.

Oracle представила возможность массового сбора данных из курсора в коллекцию PL/SQL в версии 10.1. Это гораздо более эффективный способ получения данных из SQL engine в коллекцию PL/SQL, поскольку он позволяет минимизировать сдвиги контекста, извлекая сразу несколько строк. И последующие операции над этими коллекциями более эффективны, потому что ваш код может оставаться в ядре PL/SQL.

для того чтобы принять максимальное преимущество большей части собирает синтаксис, однако, вы обычно должны использовать явные курсоры, потому что таким образом вы можете заполнить коллекцию PL/SQL, а затем использовать синтаксис FORALL для записи данных обратно в базу данных (при разумном предположении, что если вы получаете кучу данных в курсоре, существует большая вероятность того, что вы делаете какие-то манипуляции и сохраняете манипулированные данные где-то). Если вы используете неявный курсор в цикле FOR, Как правильно указывает OMG Ponies, Oracle будет выполнение массового сбора за кулисами, чтобы сделать выборку данных менее дорогостоящей. Но ваш код будет выполнять более медленные вставки и обновления строки за строкой, потому что данные не находятся в коллекции. Явные курсоры также предлагают возможность явно установить предел, который может улучшить производительность по умолчанию 100 для неявного курсора в цикле FOR.

В общем случае, предполагая, что вы находитесь на 10.2 или выше и что ваш код извлекает данные и записывает их обратно в базы данных

быстрый

  1. явные курсоры, выполняющие массовый сбор в локальную коллекцию (с соответствующим ограничением) и использующие FORALL для записи обратно в базу данных.
  2. неявные курсоры делают массовый сбор для вас за кулисами вместе с однорядной записью обратно в базу данных.
  3. явные курсоры, которые не выполняют массовый сбор и не используют преимущества PL / SQL коллекции.

медленная

с другой стороны, использование неявных курсоров дает вам довольно много преимуществ использования массовых операций для очень небольшой первоначальной стоимости при рефакторинге старого кода или изучении новой функции. Если большая часть вашей разработки PL / SQL выполняется разработчиками, основным языком которых является что-то другое или которые не обязательно следят за новыми языковыми функциями, для циклов будет легче понять и поддерживать чем явный код курсора, который использовал все новые функции массового сбора. И когда Oracle вводит новые оптимизации в будущем, гораздо более вероятно, что неявный код курсора получит преимущество автоматически, в то время как явный код может потребовать некоторой ручной переработки.

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


OPEN / FETCH / CLOSE называется явным синтаксисом курсора; последний называется неявным синтаксисом курсора.

одно ключевое отличие, которое вы уже заметили, заключается в том, что вы не можете использовать %FOUND/%NOTFOUND/etc в неявных курсорах... Другое дело, что неявные курсоры быстрее, чем явные-они читают вперед (~100 записей?) кроме того, не поддерживает явную логику.

дополнительная информация:


Я не знаю о каких-либо кардинальных отличий в этих двух реализациях, кроме одного: for ... loop неявно закрывает курсор после завершения цикла и если open ... fetch ... close синтаксис вы бы предпочли закрыть курсор самостоятельно (просто хороший способ) - думал, что это не обязательно: Oracle автоматически закроет курсор, исходящий из области видимости. Также вы не можете использовать %FOUND и %NOTFOUND на for ... loop курсоры.

как мне найти for ... loop реализация гораздо легче читать и поддержка.


поправьте меня, если я ошибаюсь, но я думаю, что у обоих есть одна хорошая функция, чего у другого нет.

С for loop вы можете сделать следующее:

for i in (select * from dual)
  dbms_output.put_line('ffffuuu');
end loop;

и с открытыми .. fetch вы можете сделать так:

declare
  cur sys_refcursor;
  tmp dual.dummy%type;
begin
  open cur for 'select dummy from dual';
  loop
    fetch cur into tmp;
    exit when cur%notfound;
    dbms_output.put_line('ffffuuu');
  end loop;
  close cur;
end;

таким образом, с open fetch вы можете использовать динамические курсоры, но с for loop вы можете определить обычный курсор без объявления.