Обработка ошибок в pl / sql - PullRequest
1 голос
/ 28 июня 2010

Я хочу знать об обработке ошибок в PL / SQL. Может ли кто-нибудь помочь мне найти краткое описание по этой теме?

Ответы [ 2 ]

5 голосов
/ 28 июня 2010

Каждый блок может иметь обработчик исключений. Пример:

DECLARE
    /* declare your variables */
BEGIN
    /*Here is your code */
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        /* HAndle an error that gets raised when a query returns nothing */
    WHEN TOO_MANY_ROWS THEN
        /* HAndle the situation when too much data is returned such as with a select-into */
    WHEN OTHERS THEN
        /* Handle everything else*/
END;

Эта ссылка расскажет вам больше: http://download.oracle.com/docs/cd/B13789_01/appdev.101/b10807/07_errs.htm

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

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

3 голосов
/ 29 июня 2010

Стоит прочитать статью Oracle, на которую есть ссылка в другом ответе.

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

Это может затруднить отладку блоков кода, содержащих несколько мест, которые могут вызвать одно и то же исключение (т. Е. Если у вас несколько операторов SQL, которые могут возвращать NO_DATA_FOUND). Один из вариантов здесь - записать полный стек ошибок как часть вашего обработчика исключений.

EXCEPTION
    WHEN TOO_MANY_ROWS THEN
         myLogger('Some useful information',DBMS_UTILITY.FORMAT_ERROR_STACK);
END;

Если вам нужно перехватывать исключения, сохраняйте обработку исключений как можно более локальной, до точки, которую вы хотите перехватить, и используйте только КОГДА ДРУГОЕ в крайнем случае.

Вы также можете «сделать что-то и повторно вызвать то же исключение»

EXCEPTION
     WHEN TOO_MANY_ROWS THEN
         closeSmtpConnection;
         RAISE;
END;

Одной из наиболее полезных функций является возможность именовать и перехватывать внутренние исключения Oracle SQL.

DECLARE
   recompile_failed     EXCEPTION;
   PRAGMA EXCEPTION_INIT (recompile_failed,-24344);
BEGIN
   . . . . . .
EXCEPTION
   WHEN recompile_failed THEN 
      emailErrors(pObjectType,pObjectName);
END;

Обратной стороной этого является возможность вызывать определенные пользователем исключения SQL

RAISE_APPLICATION_ERROR(-20001,'my text')

Это единственный способ распространения пользовательского текста в вызывающем приложении, так как пользовательские исключения pl / sql не пересекают границу области действия.

К сожалению, несмотря на то, что в документации сказано, что диапазон от -20000 до -20999 доступен для определенных пользователем исключений, некоторые из пакетов расширений Oracle используют эти серийные номера, поэтому вы не можете полагаться только на серийный номер для определения ошибки в языке вызова .

(Большинство людей, как правило, переносят RAISE_APPLICATION_ERROR в другой код, чтобы также регистрировать ошибку и часто выводить текст ошибки из таблицы)

Один трюк, который я нашел полезным, - это создать пакет с переменными состояния в теле пакета и простыми функциями установки и получения. В отличие от обновлений базы данных, информация в пакетах НЕ откатывается при ошибке.

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

Что касается пользовательских исключений pl / sql - они могут быть полезны в локальном коде, но во многих случаях их можно избежать, используя другую структуру управления (т. Е. Избегайте их использования в качестве альтернативного GOTO).

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

Пройдя по этому самому маршруту в прошлом, я бы порекомендовал против него - сделать пакеты автономными и либо использовать RAISE_APPLICATION_ERROR, либо возвращать ошибки в виде текста.

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