Разница между неявным и явным курсорами в Oracle - PullRequest
2 голосов
/ 21 сентября 2010

Я хочу знать разницу между этими двумя утверждениями.Один «лучше» другого?

DECLARE
    myvar varchar2(50);
BEGIN
    SELECT fieldone into myvar FROM tbl_one WHERE id = 1;
END;

И

DECLARE
    CURSOR L1 IS
    SELECT fieldone FROM tbl_one WHERE id = 1;
BEGIN
    OPEN L1;
    FETCH L1 INTO myvar;
    CLOSE L1;
END;

Ответы [ 5 ]

11 голосов
/ 21 сентября 2010

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

Второй произойдет сбой молча.Если строки не возвращаются, тогда myvar будет иметь нулевое значение (хотя и предпочтительнее, если вы предполагаете, что оно не определено).Если будет возвращено более одной строки, сохраняется только значение из первой строки.Без ORDER BY значение 'first' не определено.Это называется явным курсором.

Таким образом, вопрос действительно в том, что ВЫ хотите, чтобы произошло в случае отсутствия данных или ситуации с слишком большим количеством строк.Если вы уверены, что этого никогда не произойдет, или не знаете, как с этим справиться, перейдите к варианту 1.

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

Если вы ожидаете несколько строк, то либо неявный курсор с обработчиком исключений, либо BULK SELECT, либо CURSOR LOOP, если вам действительно нужно обработать несколько строк.

Если вы собираетесьвыберите несколько полей, может быть полезно определить явный курсор и использовать объявление% TYPE для объявления всех необходимых переменных.

С точки зрения производительности, нет никакой разницы.С точки зрения поддержки, некоторым людям нравится, когда их SELECT встроен в код (поэтому предпочитают неявный курсор).Я предпочитаю свой «вне пути», особенно если есть большой список столбцов, поэтому мне нравятся явные курсоры.

5 голосов
/ 21 сентября 2010

Я не знаю, какой вопрос вы задаете, но здесь идет.

Если вы используете PL / SQL, как это?

declare
  myvar varchar2(50);
begin
  select fieldone 
    into myvar
    from tbl_one;
end;
/

Ну, вы можете, если и только если , вы знаете, что оператор select может вернуть ровно одну строку; в качестве альтернативы вам потребуется обработка ошибок для исключений TOO_MANY_ROWS и NO_DATA_FOUND, которые возникли бы в противном случае.


При использовании явных курсоров (т. Е. Ключевого слова CURSOR) существует несколько операций с ним, которые управляют его поведением.

declare
  myvar varchar2(50);
  CURSOR L1 IS
  SELECT fieldone FROM tbl_one ;
begin
  OPEN L1;
  FETCH L1 into myvar;
  CLOSE L1;
end;
/

CURSOR L1... - это объявление курсора. Это не что иное, как связывание статического оператора SQL, и все, что делает движок PL / SQL, это проверка синтаксической и контекстной достоверности SQL - есть ли пропущенные предложения? Может ли этот пользователь ВЫБРАТЬ из этой таблицы?

OPEN L1 открывает курсор, устанавливая точную точку в истории системы, которая будет отражать результаты. Любые последующие FETCH для этого курсора будут отражать данные на эту точную точку.

FETCH L1... фактически возвращает первую / следующую строку этого результирующего набора, каким бы он ни был, в указанные вами переменные. Это может быть объявленная запись или список переменных.

CLOSE L1... освобождает любые ресурсы, открытые вашим курсором; например, операции вставки / обновления / удаления, которые влияют на записи, вызывают отмену, в которой ваш пользовательский сеанс имеет объявленный интерес для чтения, поэтому отмену нельзя освободить или использовать повторно, пока вы не закроете курсор.

2 голосов
/ 23 сентября 2010

Как правило, чем меньше кода вы пишете, тем надежнее ваше решение. Вот почему мы больше не предпочитаем языки уровня ассемблера.

Эта идея, примененная к курсорам, была красноречиво раскритикована Джо Селко в одной из его книг:

Курсор - это способ преобразования набора результатов запроса в поток, который может обрабатываться на языке хоста 3GL. Курсоры не совместимы между различными поставщиками СУБД и обычно работают медленнее, чем декларативные запросы SQL. Тогда зачем? Главным образом из-за незнания основ базы данных и старых привычек. Вот подробная аналогия:

<code>
ALLOCATE   = turn tape recorder power on, assign  channel<br>
DECLARE  CURSOR FOR ... = mount the tape and declare file<br>
OPEN  = open the file<br>
FETCH   INTO  = read in the program records one by one, move the head<br>
CLOSE  = close file, dismount tape from the recorder<br>
DEALLOCATE  = free tape recorder channel, power off

Эта цитата особенно смешно читается в русском переводе его «стиля программирования SQL», где «магнитофон» звучит как «аудиокассета». И предположение, что кто-то до сих пор пользуется магнитофоном в мире, кишащем iPod, iPhone и тому подобным, просто смешно.

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

1 голос
/ 23 сентября 2010

В Oracle (в отличие от SQL Server) все SELECT являются курсорами - все, что объявляет курсор, это дает вам дескриптор, который вы затем можете использовать для манипулирования им. План выполнения будет идентичным в обоих ваших случаях.

1 голос
/ 21 сентября 2010

Лично я получил бы за первую версию, когда это было возможноБудь проще.Одно утверждение вместо пяти, более читабельное.

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