К сожалению, многие программисты не склонны тратить время на то, чтобы застраховать свой код PL/SQL от всех возможных неожиданностей. У большинства из нас хватает проблем с написанием кода, реализующего положительные аспекты приложения: управление данными клиентов, построение счетов и т. д.; вдобавок это увеличивает объем работы. Всегда бывает дьявольски сложно — как с психологической точки зрения, так и в отношении расходования ресурсов — сосредоточиться на негативных аспектах работы системы: что, если пользователь нажмет не ту клавишу? А что делать, если база данных Oracle недоступна?
В результате мы пишем приложения PL/SQL, предназначенные для работы в «идеальном мире», где в программах не бывает ошибок, пользователи вводят лишь правильные данные, а все системы — и аппаратные и программные — всегда в полном порядке.
Конечно, жестокая реальность устанавливает свои правила: как бы вы ни старались, в приложении все равно отыщется еще одна ошибка. А ваши пользователи всегда постараются отыскать последовательность нажатий клавиш, от которых форма перестанет работать. Проблема проста: либо вы выделяете время на отладку и защиту своих программ, либо вам придется вести бесконечные бои в отступлении, принимая отчаянные звонки от пользователей и пытаясь потушить разгорающееся пламя.
К счастью, PL/SQL предоставляет достаточно мощный и гибкий механизм перехвата и обработки ошибок. И вполне возможно написать на языке PL/SQL такое приложение, которое полностью защитит от ошибок и всех пользователей, и базу данных Oracle.
Основные концепции и терминология обработки исключений
В языке PL/SQL ошибки всех видов интерпретируются как исключения — ситуации, которые не должны возникать при нормальном выполнении программы.
К числу исключений относятся:
- ошибки, генерируемые системой (например, нехватка памяти или повторяющееся значение индекса);
- ошибки, вызванные действиями пользователя;
- предупреждения, выдаваемые приложением пользователю.
PL/SQL перехватывает ошибки и реагирует на них при помощи так называемых обработчиков исключений. Механизм обработчиков исключений позволяет четко отделить код обработки ошибок от основной логики программы, а также дает возможность реализовать обработку ошибок, управляемую событиями (в отличие от старой линейной модели). Независимо от того, как и по какой причине возникло конкретное исключение, оно всегда обрабатывается одним и тем же обработчиком в разделе исключений.
При возникновении ошибки — как системной, так и ошибки в приложении — в PL/SQL инициируется исключение. В результате выполнение блока прерывается, и управление передается для обработки в раздел исключений текущего блока, если он имеется. После обработки исключения возврат в тот блок, где исключение было инициировано, невозможен, поэтому управление передается во внешний блок.
Схема передачи управления при возникновении исключения показана на рис. 1.
Рис. 1. Архитектура обработки исключений
Существует два типа исключений:
- Системное исключение определяется в Oracle и обычно инициируется исполняемым ядром PL/SQL, обнаружившим ошибку. Одним системным исключениям присваиваются имена (например,
NO_DATA_FOUND
), другие ограничиваются номерами и описаниями. - Исключение, определяемое программистом, актуально только для конкретного приложения. Имя исключения можно связать с конкретной ошибкой Oracle с помощью директивы компилятора
EXCEPTION_INIT
или же назначить ошибке номер и описание процедуройRAISE_APPLICATION_ERROR
.
В этом блоге будут использоваться следующие термины:
- Раздел исключений — необязательный раздел блока PL/SQL (анонимного блока, процедуры, функции, триггера или инициализационного раздела пакета), содержащий один или несколько обработчиков исключений. Структура раздела исключений очень похожа на структуру команды
CASE
, о которой рассказывалось в этом блоге. - Инициировать исключение — значит остановить выполнение текущего блока PL/SQL, оповещая исполняемое ядро об ошибке. Исключение может инициировать либо Oracle, либо ваш собственный программный код при помощи команды
RAISE
или процедурыRAISE_APPLICATION_ERROR
. - Обработать исключение — значит перехватить ошибку, передав управление обработчику исключения. Написанный программистом обработчик может содержать код, который в ответ на исключение выполняет определенные действия (например, записывает информацию об ошибке в журнал, выводит сообщение для пользователя или передает исключение во внешний блок).
- Область действия — часть кода (конкретный блок или весь раздел), в котором может инициироваться исключение, а также часть кода, инициируемые исключения которого могут перехватываться и обрабатываться соответствующим разделом исключений.
- Передача исключения — процесс передачи исключения во внешний блок, если в текущем блоке это исключение не обработано.
- Необработанное исключение — исключение, которое передается без обработки из «самого внешнего» блока PL/SQL. После этого управление передается исполнительной среде, которая уже сама определяет, как отреагировать на исключение (выполнить откат транзакции, вывести сообщение об ошибке, проигнорировать ее и т. д.).
- Анонимное исключение — исключение, с которым связан код ошибки и описание. Такое исключение не имеет имени, которое можно было бы использовать в команде
RAISE
или секцииWHEN
обработчика исключений. - Именованное исключение — исключение, которому имя присвоено либо Oracle (в одном из встроенных пакетов), либо разработчиком. В частности, для этой цели можно использовать директиву компилятора
EXCEPTION_INIT
(в таком случае имя можно будет применять и для инициирования, и для обработки исключения).
Определение исключений
Прежде чем исключение можно будет инициировать и обрабатывать, его необходимо определить. В Oracle заранее определены тысячи исключений, большинство из которых имеют только номера и пояснительные сообщения. Имена присваиваются только самым распространенным исключениям.
Имена присваиваются в пакете STANDARD
(одном из двух пакетов по умолчанию PL/SQL; другой пакет — DBMS_STANDARD
), а также в других встроенных пакетах, таких как UTL_FILE
и DBMS_SQL
. Код, используемый Oracle для определения исключений (таких, как NO_DATA_FOUND
), не отличается от кода, который вы будете использовать для определения или объявления ваших собственных исключений.
Это можно сделать двумя способами, описанными ниже.
Объявление именованных исключений
Исключения PL/SQL, объявленные в пакете STANDARD
и в других встроенных пакетах, представляют внутренние (то есть системные) ошибки. Однако многие проблемы, с которыми будет сталкиваться пользователь приложения, актуальны только в этом конкретном приложении. Возможно, вашей программе придется перехватывать и обрабатывать такие ошибки, как «отрицательный баланс счета» или «дата обращения не может быть меньше текущей даты». Хотя эти ошибки имеют иную природу, нежели, скажем, ошибки «деления на нуль», они также относятся к разряду исключений, связанных с нормальной работой программы, и должны обрабатываться этой программой.
Одной из самых полезных особенностей обработки исключений PL/SQL является отсутствие структурных различий между внутренними ошибками и ошибками конкретных приложений. Любое исключение может и должно обрабатываться в разделе исключений независимо от типа ошибки.
Конечно, для обработки исключения необходимо знать его имя. Поскольку в PL/SQL имена пользовательским исключениям автоматически не назначаются, вы должны делать это самостоятельно, определяя исключения в разделе объявлений блока PL/SQL. При этом задается имя исключения, за которым следует ключевое слово EXCEPTION
:
имя_исключения EXCEPTION;
Следующий раздел объявлений процедуры calc_annual_sales
содержит два объявления исключений, определяемых программистом:
PROCEDURE calc_annual_sales(company_id_in IN company.company_id%TYPE)
IS
invalid_company_id EXCEPTION;
negative_balance EXCEPTION;
duplicate_company BOOLEAN;
BEGIN
... исполняемые команды ...
EXCEPTION
WHEN NO_DATA_FOUND -- системное исключение
THEN
...
WHEN invalid_company_id
THEN
WHEN negative_balance
THEN
...
END;
По своему формату имена исключений схожи с именами других переменных, но ссылаться на них можно только двумя способами:
- В команде RAISE, находящейся в исполняемом разделе программы (для инициирования исключения):
RAISE invalid_company_id;
- В секции WHEN раздела исключений (для обработки инициированного исключения):
WHEN invalid_company_id THEN
Связывание имени исключения с кодом ошибки
В Oracle, как уже было сказано, имена определены лишь для самых распространенных исключений. Тысячи других ошибок в СУБД имеют лишь номера и снабжены пояснительными сообщениями. Вдобавок инициировать исключение с номером ошибки (в диапазоне от –20 999 до –20 000) может и разработчик приложения, воспользовавшись для этой цели процедурой RAISE_APPLICATION_ERROR
(см. далее раздел «Инициирование исключений»).
Наличие в программном коде исключений без имен вполне допустимо, но такой код малопонятен и его трудно сопровождать. Допустим, вы написали программу, при выполнении которой Oracle выдает ошибку, связанную с данными, например ORA-01843: not a valid month
. Для перехвата этой ошибки в программу включается обработчик следующего вида:
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -1843 THEN
Но код получается совершенно непонятным. Чтобы сделать смысл этого кода более очевидным, следует воспользоваться директивой EXCEPTION_INIT
.
Встроенная функция SQLCODE возвращает номер последней сгенерированной ошибки. Она будет рассмотрена далее в разделе «Обработка исключений» этой статьи.
Директива EXCEPTION_INIT
Директива компилятора EXCEPTION_INIT
(команда, выполняемая во время компиляции) связывает идентификатор, объявленный с ключевым словом EXCEPTION
, с внутренним кодом ошибки. Установив такую связь, можно инициировать исключение по имени и указать это имя в условии WHEN
обработчика ошибок.
С директивой EXCEPTION_INIT
условие WHEN
, использованное в предыдущем примере, приводится к следующему виду:
PROCEDURE my_procedure
IS
invalid_month EXCEPTION;
PRAGMA EXCEPTION_INIT (invalid_month, −1843);
BEGIN
...
EXCEPTION
WHEN invalid_month THEN
Жесткое кодирование номера ошибки становится излишним; имя ошибки говорит само за себя.
Директива EXCEPTION_INIT
должна располагаться в разделе объявлений блока. Указанное в ней исключение должно быть объявлено либо в том же блоке, либо во внешнем, либо в спецификации пакета. Синтаксис директивы в анонимном блоке:
DECLARE
имя_исключения EXCEPTION;
PRAGMA EXCEPTION_INIT (имя_исключения, целое_число);
Здесь имя_исключения
— имя исключения, объявляемого программистом, а целое_число
— номер ошибки Oracle, которую следует связать с данным исключением. Номером ошибки может служить любое число со следующими ограничениями:
- Номер ошибки не может быть равен –1403 (один из двух кодов ошибок
NO_DATA_FOUND
). Если вы по какой-либо причине захотите связать свое именованное исключение с этой ошибкой, передайте директивеEXCEPTION_INIT
значение 100. - Номер ошибки не может быть равен 0 или любому положительному числу, кроме 100.
- Номер ошибки не может быть отрицательным числом, меньшим –1 000 000.
Рассмотрим пример возможного объявления исключения. В приведенном ниже программном коде я объявляю и связываю исключение со следующим номером:
ORA-2292 integrity constraint (OWNER.CONSTRAINT) violated -
child record found.
Ошибка происходит при попытке удаления родительской записи, у которой в таблице имеются дочерние записи (то есть записи с внешним ключом, ссылающимся на родительскую запись):
PROCEDURE delete_company (company_id_in IN NUMBER)
IS
/* Объявление исключения. */
still_have_employees EXCEPTION;
/* Имя исключения связывается с номером ошибки. */
PRAGMA EXCEPTION_INIT (still_have_employees, 2292);
BEGIN
/* Попытка удаления информации о компании. */
DELETE FROM company
WHERE company_id = company_id_in;
EXCEPTION
/* При обнаружении дочерних записей инициируется это исключение! */
WHEN still_have_employees
THEN
DBMS_OUTPUT.PUT_LINE
('Пожалуйста, сначала удалите данные о служащих компании.');
END;
Рекомендации по использованию EXCEPTION_INIT
Директиву EXCEPTION_INIT
целесообразно использовать в двух ситуациях:
- при необходимости присвоить имя безымянному системному исключению, задействованному в программе (следовательно, если в Oracle не определено имя для некоторой ошибки, это еще не означает, что с ней можно работать только по номеру);
- когда нужно присвоить имя специфическому для приложения исключению, инициируемому процедурой
RAISE_APPLICATION_ERROR
(см. далее раздел «Инициирование исключений»). Это позволяет обрабатывать данное исключение по имени, а не по номеру.
В обоих случаях все директивы EXCEPTION_INIT
желательно объединить в пакет, чтобы определения исключений не были разбросаны по всему коду приложения. Допустим, вы интенсивно используете динамический SQL, и при выполнении запросов часто возникает ошибка «invalid column name» (неверное имя столбца). Запоминать код ошибки не хочется, но и определять директивы имя для исключения в 20 разных программах тоже неразумно. Поэтому имеет смысл определить собственные «системные исключения» в отдельном пакете для работы с динамическим SQL:
CREATE OR REPLACE PACKAGE dynsql
IS
invalid_table_name EXCEPTION;
PRAGMA EXCEPTION_INIT (invalid_table_name, -903);
invalid_identifier EXCEPTION;
PRAGMA EXCEPTION_INIT (invalid_identifier, -904);
Теперь перехват этих ошибок в программе может производиться следующим образом:
WHEN dynsql.invalid identifier THEN ...
Аналогичный подход рекомендуется использовать при работе с кодами ошибок –20NNN, передаваемыми процедуре RAISE_APPLICATION_ERROR
(см. далее в этой заметке моего блога). Создайте пакет, в котором этим кодам будут присваиваться имена. Он может выглядеть примерно так:
PACKAGE errnums
IS
en_too_young CONSTANT NUMBER := -20001;
exc_too_young EXCEPTION;
PRAGMA EXCEPTION_INIT (exc_too_young, -20001);
en_sal_too_low CONSTANT NUMBER := -20002;
exc_sal_too_low EXCEPTION;
PRAGMA EXCEPTION_INIT (exc_sal_too_low , -20002);
END errnums;
При наличии такого пакета можно использовать код следующего вида, не указывая номер ошибки в коде:
PROCEDURE validate_emp (birthdate_in IN DATE)
IS
min_years CONSTANT PLS_INTEGER := 18;
BEGIN
IF ADD_MONTHS (SYSDATE, min_years * 12 * -1) < birthdate_in
THEN
RAISE_APPLICATION_ERROR
(errnums.en_too_young,
'Возраст работника должен быть не менее ' || min_years || ' лет.');
END IF;
END;
Именованные системные исключения
В Oracle для относительно небольшого количества исключений определены стандартные имена, задаваемые директивой компилятора EXCEPTION_INIT
во встроенных пакетах. Самые важные и часто применяемые из них определены в пакете STANDARD
. Так как это один из двух используемых по умолчанию пакетов PL/SQL, на определенные в нем исключения можно ссылаться без префикса с именем пакета. Например, если потребуется инициировать в программе исключение NO_DATA_FOUND
, это можно сделать любой из следующих команд:
WHEN NO_DATA_FOUND THEN
WHEN STANDARD.NO_DATA_FOUND THEN
Определения стандартных именованных исключений встречаются и в других встроенных пакетах — например, в пакете DBMS_LOB
, предназначенном для работы с большими объектами. Пример одного такого определения из указанного пакета:
invalid_argval EXCEPTION;
PRAGMA EXCEPTION_INIT(invalid_argval, -21560);
Поскольку пакет DBMS_LOB
не используется по умолчанию, перед ссылкой на это исключение необходимо указать имя пакета:
WHEN DBMS_LOB.invalid_argval THEN...
Многие исключения, определенные в пакете STANDARD
, перечислены в табл. 1. Для каждого из них приводится номер ошибки Oracle, значение, возвращаемое при вызове SQLCODE
(встроенная функция SQLCODE
, которая возвращает текущий код ошибки — см. раздел «Встроенные функции ошибок»), и краткое описание. Значение, возвращаемое SQLCODE
, совпадает с кодом ошибки Oracle, с одним исключением: определяемый стандартом ANSI код ошибки NO_DATA_FOUND
равен 100.
Имя исключения/Ошибка Oracle/SQLCODE | Описание |
CURSOR_ALREADY_OPEN ORA-6511 SQLCODE = –6511 | Попытка открытия курсора, который был открыт ранее. Перед повторным открытием курсор необходимо сначала закрыть |
DUP_VAL_ON_INDEX ORA-00001 SQLCODE = −1 | Команда INSERT или UPDATE пытается сохранить повторяющиеся значения в столбцах, объявленных с ограничением UNIQUE |
INVALID_CURSOR ORA-01001 SQLCODE = −1001 | Ссылка на несуществующий курсор. Обычно ошибка встречается при попытке выборки данных из неоткрытого курсора или закрытия курсора до его открытия |
INVALID_NUMBER ORA-01722 SQLCODE = −1722 | Выполняемая SQL-команда не может преобразовать символьную строку в число. Это исключение отличается от VALUE_ERROR тем, что оно инициируется только из SQL-команд |
LOGIN_DENIED ORA-01017 SQLCODE = −1017 | Попытка программы подключиться к СУБД Oracle с неверным именем пользователя или паролем. Исключение обычно встречается при внедрении кода PL/SQL в язык 3GL |
NO_DATA_FOUND ORA-01403 SQLCODE = +100 | Исключение инициируется в трех случаях: (1) при выполнении инструкции SELECT INTO (неявный курсор), которая не возвращает ни одной записи; (2) при ссылке на неинициализированную запись локальной таблицы PL/SQL; (3) при попытке выполнить операцию чтения после достижения конца файла при использовании пакета UTL_FILE |
NOT_LOGGED ON ORA-01012 SQLCODE = −1012 | Программа пытается обратиться к базе данных (обычно из инструкции DML) до подключения к СУБД Oracle |
PROGRAM_ERROR ORA-06501 SQLCODE = −6501 | Внутренняя программная ошибка PL/SQL. В сообщении об ошибке обычно предлагается обратиться в службу поддержки Oracle |
STORAGE_ERROR ORA-06500 SQLCODE = −6500 | Программе PL/SQL не хватает памяти или память по какой-то причине повреждена |
TIMEOUT_ON_RESOURCE ORA-00051 SQLCODE = −51 | Тайм-аут СУБД при ожидании ресурса |
TOO_MANY_ROWS ORA-01422 SQLCODE = −1422 | Команда SELECT INTO возвращает несколько записей, хотя должна возвращать лишь одну (в таких случаях инструкция SELECT включается в явное определение курсора, а записи выбираются по одной) |
TRANSACTION_BACKED_OUT ORA-00061 SQLCODE = −61 | Удаленная часть транзакции отменена либо при помощи явной инструкции ROLLBACK , либо в результате какого-то другого действия (например, неудачного выполнения команды SQL или DML в удаленной базе данных) |
VALUE_ERROR ORA-06502 SQLCODE = −6502 | Ошибка связана с преобразованием, усечением или проверкой ограничений числовых или символьных данных. Это общее и очень распространенное исключение. Если подобная ошибка содержится в инструкции SQL или DML, то в блоке PL/SQL инициируется исключение INVALID_NUMBER |
ZERO_DIVIDE ORA-01476 SQLCODE = −1476 | Попытка деления на ноль |
Рассмотрим пример использования этой таблицы исключений. Предположим, ваша программа инициирует необрабатываемое исключение для ошибки ORA-6511. Заглянув в таблицу, вы видите, что она связана с исключением CURSOR_ALREADY_OPEN
. Найдите блок PL/SQL, в котором произошла ошибка, и добавьте в него обработчик исключения
CURSOR_ALREADY_OPEN:
EXCEPTION
WHEN CURSOR_ALREADY_OPEN
THEN
CLOSE my_cursor;
END;
Конечно, еще лучше было бы проанализировать весь программный код и заранее определить, какие из стандартных исключений в нем могут инициироваться. В таком случае вы сможете решить, какие исключения следует обрабатывать конкретно, какие следует включить в конструкцию WHEN OTHERS
(см. далее), а какие оставить необработанными.
Область действия исключения
Областью действия исключения называется та часть программного кода, к которой оно относится, то есть блок, где данное исключение может быть инициировано. В следующей таблице указаны области действия исключений четырех разных типов.
Тип исключения | Область действия |
Именованное системное исключение | Исключение является глобальным, то есть не ограничивается каким-то конкретным блоком кода. Системные исключения могут инициироваться и обрабатываться в любом блоке |
Именованное исключение, определяемое программистом | Исключение может инициироваться и обрабатываться только в исполнительном разделе и разделе исключений, входящих в состав блока, где объявлено данное исключение (или в состав любого из вложенных в него блоков). Если исключение определено в спецификации пакета, то его областью действия являются все те программы, владельцы которых обладают для этого пакета привилегией EXECUTE |
Анонимное системное исключение | Исключение может обрабатываться в секции WHEN OTHERS любого раздела исключений PL/SQL. Если присвоить ему имя, то его область действия будет такой же, как у именованного исключения, определяемого программистом |
Анонимное исключение, определяемое программистом | Исключение определяется в вызове процедуры RAISE_APPLICATION_ERROR , а затем передается в вызывающую программу |
Рассмотрим пример исключения overdue_balance
, объявленного в процедуре check_account
(таким образом, область его действия ограничивается указанной процедурой):
PROCEDURE check_account (company_id_in IN NUMBER)
IS
overdue_balance EXCEPTION;
BEGIN
... исполняемые команды ...
LOOP
...
IF ... THEN
RAISE overdue_balance;
END IF;
END LOOP;
EXCEPTION
WHEN overdue_balance THEN ...
END;
С помощью команды RAISE
исключение overdue_balance
можно инициировать в процедуре check_account
, но не в программе, которая ее вызывает. Например, для следующего анонимного блока компилятор выдает ошибку:
DECLARE
company_id NUMBER := 100;
BEGIN
check_account (100);
EXCEPTION
WHEN overdue_balance /* В PL/SQL такая ссылка недопустима. */
THEN ...
END;
PLS-00201: identifier "OVERDUE_BALANCE" must be declared
Для приведенного выше анонимного блока процедура check_account
является «черным ящиком». Все объявленные в ней идентификаторы, в том числе идентификаторы исключения, не видны для внешнего программного кода.
Инициирование исключений
Исключение может быть инициировано приложением в трех случаях:
- Oracle инициирует исключение при обнаружении ошибки;
- приложение инициирует исключение командой
RAISE
; - исключение инициируется встроенной процедурой
RAISE_APPLICATION_ERROR
.
Как Oracle инициирует исключения, вы уже знаете. Теперь давайте посмотрим, как это может сделать программист.
Команда RAISE
Чтобы программист имел возможность самостоятельно инициировать именованные исключения, в Oracle поддерживается команда RAISE
. С ее помощью можно инициировать как собственные, так и системные исключения. Команда имеет три формы:
RAISE имя_исключения;
RAISE имя_пакета.имя_исключения;
RAISE;
Первая форма (без имени пакета) может инициировать исключения, определенные в текущем блоке (или в содержащем его блоке), а также системные исключения, объявленные в пакете STANDARD
. Далее приводятся два примера, в первом из которых инициируется исключение, определенное программистом:
DECLARE
invalid_id EXCEPTION; -- Все идентификаторы должны начинаться с буквы 'X'.
id_value VARCHAR2(30);
BEGIN
id_value := id_for ('SMITH');
IF SUBSTR (id_value, 1, 1) != 'X'
THEN
RAISE invalid_id;
END IF;
...
END;
При необходимости вы всегда можете инициировать системное исключение:
BEGIN
IF total_sales = 0
THEN
RAISE ZERO_DIVIDE; -- Определено в пакете STANDARD
ELSE
RETURN (sales_percentage_calculation (my_sales, total_sales));
END IF;
END;
Если исключение объявлено в пакете (но не в STANDARD
) и инициируется извне, имя исключения необходимо уточнить именем пакета:
IF days_overdue (isbn_in, borrower_in) > 365
THEN
RAISE overdue_pkg.book_is_lost;
END IF;
Третья форма RAISE
не требует указывать имя исключения, но используется только в условии WHEN
раздела исключений. Ее синтаксис предельно прост:
RAISE;
Используйте эту форму для повторного инициирования (передачи) перехваченного исключения:
EXCEPTION
WHEN NO_DATA_FOUND
THEN
-- Используем общий пакет для сохранений всей контекстной
-- информации: код ошибки, имя программы и т. д.
errlog.putline (company_id_in);
-- А теперь исключение NO_DATA_FOUND передается
-- в родительский блок без обработки.
RAISE;
Эта возможность особенно полезна в тех случаях, когда информацию об ошибке нужно записать в журнал, а сам процесс обработки возложить на родительский блок. Таким образом выполнение родительских блоков завершается без потери информации об ошибке.
Процедура RAISE_APPLICATION_ERROR
Для инициирования исключений, специфических для приложения, Oracle предоставляет процедуру RAISE_APPLICATION_ERROR
(определенную в используемом по умолчанию пакете DBMS_STANDARD
). Ее преимущество перед командой RAISE (которая тоже может инициировать специфические для приложения явно объявленные исключения) заключается в том, что она позволяет связать с исключением сообщение об ошибке.
При вызове этой процедуры выполнение текущего блока PL/SQL прекращается, а любые изменения аргументов OUT
и IN OUT
(если таковые имеются) отменяются. Изменения, внесенные в глобальные структуры данных (с помощью команды INSERT, UPDATE, MERGE
или DELETE
), такие как переменные пакетов и объекты баз данных, не отменяются. Для отката DML-команд необходимо явно указать в разделе обработки исключений команду ROLLBACK
.
Заголовок этой процедуры (определяемый в пакете DBMS_STANDARD
) выглядит так:
PROCEDURE RAISE_APPLICATION_ERROR (
num binary_integer,
msg varchar2,
keeperrorstack boolean default FALSE);
Здесь num
— номер ошибки из диапазона от –20 999 до –20 000 (только представьте: все остальные отрицательные числа Oracle резервирует для собственных исключений!); msg
— сообщение об ошибке, длина которого не должна превышать 2048 символов (символы, выходящие за эту границу, игнорируются); аргумент keeperrorstack
указывает, хотите ли вы добавить ошибку к уже имеющимся в стеке (TRUE
), или заменить существующую ошибку (значение по умолчанию — FALSE
).
Oracle выделяет диапазон номеров от –20 999 до –20 000 для пользовательских ошибок, но учтите, что в некоторых встроенных пакетах, в том числе в DBMS_OUTPUT
и DBMS_DESCRIBE
, номера от –20 005 до –20 000 все равно присваиваются системным ошибкам. За дополнительной информацией обращайтесь к документации пакетов.
Рассмотрим пример полезного применения этой встроенной процедуры. Допустим, мы хотим, чтобы сообщения об ошибках выдавались пользователям на разных языках. Создадим для них таблицу error_table
и определим в ней язык каждого сообщения значением столбца string_language
. Затем создается процедура, которая генерирует заданную ошибку, загружая соответствующее сообщение из таблицы с учетом языка текущего сеанса:
PROCEDURE raise_by_language (code_in IN PLS_INTEGER)
IS
l_message error_table.error_string%TYPE;
BEGIN
SELECT error_string
INTO l_message
FROM error_table
WHERE error_number = code_in
AND string_language = USERENV ('LANG');
RAISE_APPLICATION_ERROR (code_in, l_message);
END;
Обработка исключений
Как только в программе возникает исключение, нормальное выполнение блока PL/SQL останавливается, и управление передается в раздел исключений. Затем исключение либо обрабатывается обработчиком исключений в текущем блоке PL/SQL, либо передается в родительский блок.
Чтобы обработать или перехватить исключение, нужно написать для него обработчик. Обработчики исключений располагаются после всех исполняемых команд блока, но перед завершающим ключевым словом END
. Начало раздела исключений отмечает ключевое слово EXCEPTION
:
DECLARE
... объявления ...
BEGIN
... исполняемые команды ...
[ EXCEPTION
... обработчики исключений ... ]
END;
Синтаксис обработчика исключений может быть таким:
WHEN имя_исключения [ OR имя_исключения ... ]
THEN
исполняемые команды
или таким:
WHEN OTHERS
THEN
исполняемые команды
В одном разделе исключений может быть несколько их обработчиков. Структура обработчиков напоминает структуру условной команды CASE
.
Свойство | Описание |
EXCEPTION WHEN NO_DATA_FOUND THEN исполняемые_команды1; | Если инициировано исключение NO_DATA_FOUND , выполнить первый набор команд |
WHEN payment_overdue THEN исполняемые_команды2; | Если просрочена оплата, выполнить второй набор команд |
WHEN OTHERS THEN исполняемые_команды3; END; | Если инициировано иное исключение, выполнить третий набор команд |
Если имя, заданное в условии WHEN
, совпадает с инициированным исключением, то это исключение обрабатывается соответствующим набором команд. Обратите внимание: исключения перехватываются по именам, а не по кодам ошибок. Но если инициированное исключение не имеет имени или его имя не соответствует ни одному из имен, указанных в условиях WHEN
, тогда оно обрабатывается командами, заданными в секции WHEN OTHERS
(если она имеется). Любая ошибка может быть перехвачена только одним обработчиком исключений. После выполнения команд обработчика управление сразу же передается из текущего блока в родительский или вызывающий блок.
Секция WHEN OTHERS
не является обязательной. Когда она отсутствует, все необработанные исключения немедленно передаются в родительский блок, если таковой имеется. Секция WHEN OTHERS
должна быть последним обработчиком исключений в блоке. Если разместить после нее еще одну секцию WHEN
, компилятор выдаст сообщение об ошибке.
Встроенные функции ошибок
Прежде чем переходить к изучению тонкостей обработки ошибок, мы сначала вкратце познакомимся со встроенными функциями Oracle, предназначенными для идентификации, анализа и реагирования на ошибки, возникающие в приложениях PL/SQL.
SQLCODE
Функция SQLCODE
возвращает код ошибки последнего исключения, инициированного в блоке. При отсутствии ошибок SQLCODE
возвращает 0. Кроме того, SQLCODE
возвращает 0 при вызове за пределами обработчика исключений.
База данных Oracle поддерживает стек значений SQLCODE
. Допустим, к примеру, что функция FUNC инициирует исключение VALUE_ERROR
(–6502). В разделе исключений FUNC
вызывается процедура PROC
, которая инициирует исключение DUP_VAL_ON_INDEX
(–1). В разделе исключений PROC
функция SQLCODE
возвращает значение –1. Но когда управление передается в раздел исключений FUNC
, SQLCODE
будет возвращать –6502.
SQLERRM
Функция SQLERRM
возвращает сообщение об ошибке для заданного кода ошибки. Если вызвать SQLERRM
без указания кода ошибки, функция вернет сообщение, связанное со значением, возвращаемым SQLCODE
. Например, если SQLCODE
возвращает 0, функция SQLERRM
вернет следующую строку:
ORA-0000: normal, successful completion
Если же SQLCODE
возвращает 1 (обобщенный код ошибки для исключения, определяемого пользователем), SQLERRM
вернет строку:
User-Defined Exception
Пример вызова SQLERRM
для получения сообщения об ошибке для конкретного кода:
1 BEGIN
2 DBMS_OUTPUT.put_line (SQLERRM (-1403));
3* END;
SQL> /
ORA-01403: no data found
Максимальная длина строки, возвращаемой SQLERRM
, составляет 512 байт (в некоторых ранних версиях Oracle — 255 байт). Из-за этого ограничения Oracle Corporation рекомендует вызывать функцию DBMS_UTILITY
.FORMAT_ERROR_STACK
, чтобы гарантировать вывод полной строки (эта встроенная функция не усекает текст до 2000 байт).
DBMS_UTILITY.FORMAT_ERROR_STACK
Эта встроенная функция, как и SQLERRM
, возвращает сообщение, связанное с текущей ошибкой (то есть значение, возвращаемое SQLCODE
). Ее отличия от SQLERRM
:
- Она возвращает до 1899 символов сообщения, что позволяет избежать проблем с усечением.
- Этой функции не может передаваться код ошибки; соответственно, она не может использоваться для получения сообщения, соответствующего произвольному коду.
Как правило, эта функция вызывается в логике обработчика исключения для получения полного сообщения об ошибке.
Хотя в имя функции входит слово «stack», она не возвращает информацию о стеке ошибок, приведшем к строке, в которой изначально была инициирована ошибка. Эту задачу решает DBMS_UTILITY
.FORMAT_ERROR_BACKTRACE
.
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
Эта функция, появившаяся в Oracle10g, возвращает отформатированную строку с содержимым стека программ и номеров строк. Ее выходные данные позволяют отследить строку, в которой изначально была инициирована ошибка.
Тем самым заполняется весьма существенный пробел в функциональности PL/SQL. В Oracle9i и предшествующих версиях после обработки исключения в блоке PL/ SQL было невозможно определить строку, в которой произошла ошибка (возможно, самая важная информация для разработчика). Если программист хотел получить эту информацию, он должен был разрешить прохождение необработанного исключения, чтобы полная трассировочная информация ошибки была выведена на экран. Ситуация более подробно описана в следующем разделе.
DBMS_UTILITY.FORMAT_CALL_STACK
Функция возвращает отформатированную строку со стеком вызовов в приложении PL/SQL. Практическая полезность функции не ограничивается обработкой ошибок; она также пригодится для трассировки выполнения вашего кода.
В Oracle Database 12c появился пакет UTL_CALL_STACK
, который также предоставляет доступ к стеку вызовов, стеку ошибок и информации обратной трассировки.
Подробнее о DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
Функцию DBMS_UTILITY
.FORMAT_ERROR_BACKTRACE
следует вызывать в обработчике исключения. Она выводит содержимое стека выполнения в точке инициирования исключения. Таким образом, вызов DBMS_UTILITY
.FORMAT_ERROR_BACKTRACE
в разделе исключений на верхнем уровне стека позволит узнать, где именно в стеке вызовов произошла ошибка. Рассмотрим следующий сценарий: мы определяем процедуру proc3
, которая вызывает процедуру proc2
, а последняя, в свою очередь, вызывает proc1
. Процедура proc1 инициирует исключение:
CREATE OR REPLACE PROCEDURE proc1 IS
BEGIN
DBMS_OUTPUT.put_line ('выполнение proc1');
RAISE NO_DATA_FOUND;
END;
/
CREATE OR REPLACE PROCEDURE proc2 IS
l_str VARCHAR2 (30) := 'вызов proc1';
BEGIN
DBMS_OUTPUT.put_line (l_str);
proc1;
END;
/
CREATE OR REPLACE PROCEDURE proc3 IS
BEGIN
DBMS_OUTPUT.put_line ('вызов proc2');
proc2;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('Стек ошибок верхнего уровня:');
DBMS_OUTPUT.put_line (DBMS_UTILITY.format_error_backtrace);
END;
/
Единственной программой с обработчиком ошибок является внешняя процедура proc3
. Вызов функции трассировки включен в обработчик WHEN OTHERS
процедуры proc3
. При выполнении этой процедуры будет получен следующий результат:
SQL> SET SERVEROUTPUT ON
SQL> BEGIN
2 DBMS_OUTPUT.put_line ('Proc3 -> Proc2 -> Proc1 backtrace');
3 proc3;
4 END;
5 /
Proc3 -> Proc2 -> Proc1 backtrace
вызов proc2
вызов proc1
выполнение proc1
Error stack at top level:
ORA-06512: at "SCOTT.PROC1", line 4
ORA-06512: at "SCOTT.PROC2", line 5
ORA-06512: at "SCOTT.PROC3", line 4
Как видите, функция трассировки выводит в начале стека номер строки proc1
, в которой произошла исходная ошибка.
Часто исключение происходит где-то в глубине стека вызовов. Если вы хотите, чтобы оно было передано во внешний блок PL/SQL, вероятно, вам придется заново инициировать его в каждом обработчике стека блоков. Функция DBMS_UTILITY
.FORMAT_ERROR_BACKTRACE
выдает трассировку исполнения вплоть до последней команды RAISE
в сеансе пользователя. Учтите, что вызов RAISE
для конкретного исключения или повторное инициирование текущего исключения приводит к инициализации стека, выдаваемого DBMS_UTILITY
.FORMAT_ERROR_BACKTRACE
. Таким образом, если вы хотите использовать эту функцию, возможны два пути:
- Вызовите функцию в разделе исключений блока, в котором была инициирована ошибка. Это позволит вам получить (и сохранить в журнале) номер ошибки, даже если исключение было заново инициировано в дальнейшей позиции стека.
- Обойдите обработчики исключений в промежуточных программах вашего стека и вызовите функцию в разделе исключений внешней программы в стеке.
Только номер строки, пожалуйста
В реальном приложении трассировка ошибок может быть очень длинной. Как правило, специалиста, занимающегося отладкой или поддержкой, не интересует весь стек — достаточно только последнего элемента. Возможно, разработчику приложения стоит вывести эту важную информацию, чтобы пользователь мог немедленно и точно описать суть проблемы группе поддержки.
В такой ситуации необходимо разобрать строку с данными трассировки и извлечь из нее последний элемент. Я написал для этого специальную программу и оформил ее в пакет BT
. В этом пакете реализован простой, понятный интерфейс:
PACKAGE bt
IS
TYPE error_rt IS RECORD (
program_owner all_objects.owner%TYPE
, program_name all_objects.object_name%TYPE
, line_number PLS_INTEGER
);
FUNCTION info (backtrace_in IN VARCHAR2)
RETURN error_rt;
PROCEDURE show_info (backtrace_in IN VARCHAR2);
END bt;
Тип записи error_rt
содержит отдельное поле для каждого возвращаемого элемента трассировки (владелец программного модуля, имя программного модуля и номер строки в программе). Затем вместо того, чтобы вызывать функцию трассировки в каждом разделе исключения и разбирать ее результаты, я вызываю функцию bt.info
и вывожу конкретную информацию об ошибке.
Полезные применения SQLERRM
Вы можете использовать DBMS_UTILITY
.FORMAT_ERROR_STACK
вместо SQLERRM
, но это не означает, что функция SQLERRM
совершенно неактуальна. В частности, она поможет вам получить ответ на следующие вопросы:
- Является ли заданное число действительным кодом ошибки Oracle?
- Какое сообщение соответствует коду ошибки?
Как упоминалось ранее в нашей статье, функция SQLERRM
возвращает сообщение об ошибке для заданного кода. Но если передать SQLERRM
недействительный код, исключение не инициируется. Вместо этого возвращается строка в одном из двух форматов:
- Если число отрицательно:
ORA-NNNNN: Message NNNNN not found; product=RDBMS; facility=ORA
- Если число положительно или меньше −65535:
-N: non-ORACLE exception
Этим обстоятельством можно воспользоваться для построения функций, возвращающих точную информацию о том коде, с которым вы работаете в настоящее время. Ниже приведена спецификация пакета с этими программами:
PACKAGE oracle_error_info
IS
FUNCTION is_app_error (code_in IN INTEGER)
RETURN BOOLEAN;
FUNCTION is_valid_oracle_error (
code_in IN INTEGER
, app_errors_ok_in IN BOOLEAN DEFAULT TRUE
, user_error_ok_in IN BOOLEAN DEFAULT TRUE
)
RETURN BOOLEAN;
PROCEDURE validate_oracle_error (
code_in IN INTEGER
, message_out OUT VARCHAR2
, is_valid_out OUT BOOLEAN
, app_errors_ok_in IN BOOLEAN DEFAULT TRUE
, user_error_ok_in IN BOOLEAN DEFAULT TRUE
);
END oracle_error_info;
Объединение нескольких исключений в одном обработчике
В одном условии WHEN
можно оператором OR
объединить несколько исключений — подобно тому, как этим оператором объединяются логические выражения:
WHEN invalid_company_id OR negative_balance
THEN
В одном обработчике также можно комбинировать имена пользовательских и системных исключений:
WHEN balance_too_low OR ZERO_DIVIDE OR DBMS_LDAP.INVALID_SESSION
THEN
Впрочем, применять оператор AND
в такой комбинации нельзя, потому что в любой момент времени может быть инициировано только одно исключение.
Необработанные исключения
Исключение, инициированное в программе, но не обработанное в соответствующем разделе текущего или родительского блока PL/SQL, называется необработанным. PL/ SQL возвращает сообщение об ошибке, вызвавшей необработанное исключение, в ту среду, где была запущена данная программа. Эта среда (ею может быть SQL*Plus. Oracle Forms, программа на языке Java и т. д.) действует по ситуации. В частности, SQL*Plus осуществляет откат всех DML-инструкций, выполненных в родительском блоке.
Одним из важнейших моментов, связанных с проектированием архитектуры приложения, является вопрос о том, разрешается ли в нем использовать необработанные исключения. Такие исключения разными средами обрабатываются по-разному, и не всегда это делается корректно. Если ваша программа PL/SQL вызывается не из PL/SQL-среды, в ее «самом внешнем» блоке можно запрограммировать следующие действия:
- перехват всех исключений, которые могли быть переданы до текущей точки;
- запись информации об ошибке в журнал, с тем чтобы впоследствии ее мог проанализировать разработчик;
- возврат кода состояния, описания и другой информации, необходимой управляющей среде для выбора оптимального варианта действий.
Передача необработанного исключения
Блок, в котором может быть инициировано исключение, определяется правилами области действия исключений. В программе инициированное исключение распространяется в соответствии с определенными правилами.
Сначала PL/SQL ищет обработчик исключения в текущем блоке (анонимном блоке, процедуре или функции). Если такового нет, исключение передается в родительский блок. Затем PL/SQL пытается обработать исключение, инициировав его еще раз в родительском блоке. И так происходит в каждом внешнем по отношению к другому блоке до тех пор, пока все они не будут исчерпаны (рис. 2). После этого PL/SQL возвращает необработанное исключение в среду приложения, выполнившего «самый внешний» блок PL/SQL. И только теперь исключение может прервать выполнение основной программы.
Рис. 2. Передача исключений во вложенных блоках PL/SQL
Потеря информации об исключении
Структура процесса обработки локальных, определяемых программистом исключений в PL/SQL такова, что можно легко потерять информацию об исключении (то есть о том, какая именно произошла ошибка). Пример:
BEGIN
<<local_block>>
DECLARE
case_is_not_made EXCEPTION;
BEGIN
...
END local_block;
Допустим, мы забыли включить в этот блок раздел исключений. Область действия исключения case_is_not_made
ограничена блоком local_block
. Если исключение не обрабатывается в данном блоке, оно передается в родительский, где нет никакой информации о нем. Известно только то, что произошла ошибка, а какая именно — неизвестно. Ведь все пользовательские исключения имеют один и тот же номер ошибки 1 и одно и то же сообщение «User Defined Exception» — если только вы не воспользуетесь директивой EXCEPTION_INIT
, чтобы связать с объявленным исключением другой номер, и не присвоите ему другое сообщение об ошибке при вызове RAISE_APPLICATION_ERROR
.
Таким образом, локально объявленные (и инициированные) исключения всегда следует обрабатывать по имени.
Примеры передачи исключения
Рассмотрим несколько примеров передачи исключений через внешние блоки. На рис. 3 показано, как исключение too_many_faults
, инициированное во внутреннем блоке, обрабатывается в следующем — внешнем — блоке. Внутренний блок содержит раздел исключений, так что PL/SQL сначала проверяет, обрабатывается ли в этом разделе инициированное исключение too_many_faults
.
Рис. 3. Передача исключений во вложенных блоках PL/SQL
А поскольку оно не обрабатывается, PL/SQL закрывает этот блок и инициирует исключение too_many_faults
во внешнем блоке, обозначенном на рисунке как вложенный блок 1. (Используемые команды, расположенные после вложенного блока 2, не выполняются.) Затем просматривается раздел исключений этого блока с целью поиска обработчика исключения too_many_faults
, который обрабатывает его и передает управление процедуре list_my_faults
.
Обратите внимание: если исключение NO_DATA_FOUND
будет инициировано в «самом внутреннем» блоке, то оно будет обработано в разделе исключений этого же блока. Затем управление передается во вложенный блок 1 и будут выполнены исполняемые команды, расположенные после вложенного блока 2.
На рис. 4 представлен пример обработки в «самом внешнем» блоке исключения, инициированного во внутреннем блоке. В изображенной ситуации раздел исключений присутствует только во внешнем блоке, поэтому когда во вложенном блоке 2 инициируется исключение too_many_faults
, PL/SQL прекращает выполнение этого блока и инициирует данное исключение в его родительском блоке, то есть вложенном блоке 1. Но поскольку и у него нет раздела исключений, управление передается «самому внешнему» блоку, процедуре list_my_faults
. В этой процедуре имеется раздел исключений, поэтому PL/ SQL проверяет его, находит обработчик исключения too_many_faults
, выполняет имеющийся там код и передает управление программе, вызвавшей процедуру list_my_faults
.
Рис. 4. Исключение, инициированное во вложенном блоке,
обрабатывается в «самом внешнем» блоке
Продолжение выполнения после исключений
Когда в блоке PL/SQL инициируется исключение, нормальная последовательность выполнения программы прерывается, а управление передается в раздел исключений. Вернуться к исполняемому разделу блока после возникновения в нем исключения уже не удастся. Впрочем, в некоторых ситуациях требуется именно это — продолжить выполнение программы после обработки исключения.
Рассмотрим следующий сценарий: требуется написать процедуру, которая применяет серию операций DML к разным таблицам (удаление из одной таблицы, обновление другой, вставка в последнюю таблицу). На первый взгляд код мог бы выглядеть примерно так:
PROCEDURE change_data IS
BEGIN
DELETE FROM employees WHERE ... ;
UPDATE company SET ... ;
INSERT INTO company_history SELECT * FROM company WHERE ... ;
END;
Безусловно, процедура содержит все необходимые команды DML. Однако одно из требований к программе заключается в том, что при последовательном выполнении этих команд они должны быть логически независимы друг от друга. Другими словами, даже если при выполнении DELETE
произойдет сбой, программа должна выполнить UPDATE
и INSERT
.
В текущей версии change_data
ничто не гарантирует, что программа хотя бы попытается выполнить все три операции DML. Если при выполнении DELETE
произойдет исключение, например, то выполнение всей программы прервется, а управление будет передано в раздел исключений (если он имеется). Остальные команды SQL при этом выполняться не будут.
Как обеспечить обработку исключения без прерывания программы? Для этого DELETE
следует поместить в собственный блок PL/SQL. Рассмотрим следующую версию программы change_data
:
PROCEDURE change_data
IS
BEGIN
BEGIN
DELETE FROM employees WHERE ... ;
EXCEPTION
WHEN OTHERS THEN log_error;
END;
BEGIN
UPDATE company SET ... ;
EXCEPTION
WHEN OTHERS THEN log_error;
END;
BEGIN
INSERT INTO company_history SELECT * FROM company WHERE ... ;
EXCEPTION
WHEN OTHERS THEN log_error;
END;
END;
В новом варианте программы, если при выполнении DELETE
произойдет исключение, управление немедленно передается в раздел исключений. Но поскольку команда DELETE
теперь находится в собственном блоке, она может иметь собственный раздел исключений. Условие WHEN OTHERS
этого раздела обрабатывает ошибку без повторного инициирования этой или другой ошибки, после чего управление возвращается за пределы блока DELETE
внешней процедуре change_data
. Так как «активное» исключение отсутствует, выполнение продолжается во внешнем блоке со следующей команды процедуры. Программа входит в новый анонимный блок для команды UPDATE
. Если при выполнении UPDATE
произойдет ошибка, она будет перехвачена условием WHEN OTHERS
раздела исключений UPDATE
. Далее управление будет возвращено процедуре change_data
, которая перейдет к выполнению команды INSERT
(также содержащейся в собственном блоке).
На рис. 5 показано, как выполняется этот процесс для двух последовательно выполняемых команд DELETE
.
Рис. 5. Последовательное выполнение DELETE с разными областями действия
Подведем итог: исключение, инициированное в исполняемом разделе, всегда обрабатывается в текущем блоке (при наличии подходящего обработчика). Любую команду можно заключить в «виртуальный блок», заключив ее между ключевыми словами BEGIN
и END
с определением раздела EXCEPTION
. Это позволяет ограничить область действия сбоев в программе посредством определения «буферных» анонимных блоков.
Эту стратегию можно развить с выделением изолируемого кода в отдельные процедуры и функции. Конечно, именованные блоки PL/SQL тоже могут иметь собственные разделы исключений и предоставлять ту же защиту от общих сбоев. Важнейшее преимущество процедур и функций заключается в том, что они скрывают все команды BEGIN-EXCEPTION-END
от основной программы. Программа лучше читается, код проще сопровождать и повторно использовать в других контекстах.
Существуют и другие способы продолжить выполнение после исключения DML — например, можно использовать конструкцию SAVE EXCEPTIONS
с FORALL
и LOG ERRORS
в сочетании с DBMS_ERRORLOG
.
Написание раздела WHEN OTHERS
Условие WHEN OTHERS
включается в раздел исключений для перехвата всех исключений, не обработанных предшествующими обработчиками. Так как конкретный тип исключения изначально неизвестен, в WHEN OTHERS
очень часто используются встроенные функции для получения информации о возникшей ошибке (такие, как SQLCODE
и DBMS_UTILITY
. FORMAT_ERROR_STACK
).
В сочетании с WHEN OTHERS
функция SQLCODE
представляет средства для обработки разных видов исключений без применения директивы EXCEPTION_INIT
. В следующем примере перехватываются два исключения категории «родитель/потомок», −1 и −2292, и для каждой ситуации выполняется подходящее действие:
PROCEDURE add_company (
id_in IN company.ID%TYPE
, name_in IN company.name%TYPE
, type_id_in IN company.type_id%TYPE
)
IS
BEGIN
INSERT INTO company (ID, name, type_id)
VALUES (id_in, name_in, type_id_in);
EXCEPTION
WHEN OTHERS
THEN
/*
|| Анонимный блок в обработчике исключения позволяет объявить
|| локальные переменные для хранения информации о кодах ошибок.
*/
DECLARE
l_errcode PLS_INTEGER := SQLCODE;
BEGIN
CASE l_errcode
WHEN −1 THEN
-- Дублирующееся значение уникального индекса. Повторяется либо
-- первичный ключ, либо имя. Сообщить о проблеме
-- и инициировать исключение заново.
DBMS_OUTPUT.put_line
( 'идентификатор или имя компании уже используется. ID = '
|| TO_CHAR (id_in)
|| ' name = '
|| name_in
);
RAISE;
WHEN −2291 THEN
-- Родительский ключ не найден. Сообщить о проблеме
-- и инициировать исключение заново.
DBMS_OUTPUT.put_line (
'Недопустимый идентификатор типа компании: ' || TO_CHAR (type_id_in));
RAISE;
ELSE
RAISE;
END CASE;
END; -- Конец анонимного блока.
END add_company;
Будьте осторожны при использовании WHEN OTHERS
— этот раздел способен «поглощать» ошибки, скрывая их от внешних блоков и пользователя. А точнее, обращайте внимание на обработчики WHEN OTHERS
, которые не инициируют текущее исключение заново и не заменяют его другим исключением. Если WHEN OTHERS
не передает исключение наружу, внешние блоки вашей программы не узнают о возникшей ошибке.
В Oracle Database 11g появилось новое предупреждение, которое помогает выявлять программы, игнорирующие ошибки или поглощающие их:
PLW-06009: procedure "string" OTHERS handler does not end in RAISE or RAISE_
APPLICATION_ERROR
Пример использования этого предупреждения:
SQL> ALTER SESSION SET plsql_warnings = 'enable:all'
2 /
SQL> CREATE OR REPLACE PROCEDURE plw6009_demo
2 AS
3 BEGIN
4 DBMS_OUTPUT.put_line ('I am here!');
5 RAISE NO_DATA_FOUND;
6 EXCEPTION
7 WHEN OTHERS
8 THEN
9 NULL;
10 END plw6009_demo;
11 /
SP2-0804: Procedure created with compilation warnings
SQL> SHOW ERRORS
Errors for PROCEDURE PLW6009_DEMO:
LINE/COL ERROR
-------- -----------------------------------------------------------------
7/9 PLW-06009: procedure "PLW6009_DEMO" OTHERS handler does not end
in RAISE or RAISE_APPLICATION_ERROR
Построение эффективной архитектуры управления ошибками
Механизм инициирования и обработки ошибок в PL/SQL отличается мощью и гибкостью, но он не лишен недостатков, которые могут создать проблемы для групп разработки, желающих реализовать надежную, последовательную, содержательную архитектуру управления ошибками. В частности, вы столкнетесь со следующими проблемами:
EXCEPTION
— особая разновидность структуры данных PL/SQL. Переменные, объявленные с типомEXCEPTION
, можно только инициировать и обрабатывать. Исключение нельзя передать в аргументе программы, с ним нельзя связать дополнительные атрибуты.- Повторное использование кода обработки исключений сильно затруднено. Из предыдущего пункта непосредственно следует другой факт: раз исключение нельзя передать в аргументе, разработчику приходится копировать код обработчика — конечно, такой способ написания кода никак не назовешь оптимальным.
- Не существует формализованного способа объявления исключений, которые могут инициироваться программой. Например, в Java эта информация становится частью спецификации программы. Как следствие, разработчику приходится обращаться к коду реализации и искать в нем информацию о потенциальных исключениях — или же надеяться на лучшее.
- Oracle не предоставляет средств организации и классификации исключений, относящихся к конкретному приложению, а просто резервирует (в основном) 1000 кодов в диапазоне от −20 999 до −20 000. Управлять этими значениями должен сам разработчик.
Давайте посмотрим, как преодолеть большинство из перечисленных трудностей.
Определение стратегии управления ошибками
Очень важно, чтобы еще до написания кода была выработана последовательная стратегия и архитектура обработки ошибок в приложении. Вот лишь некоторые вопросы, на которые необходимо ответить для этого:
- Как и когда сохранять информацию об ошибках для последующего просмотра и исправления? Куда выводить информацию — в файл, в таблицу базы данных? выводить на экран?
- Как и где сообщать об ошибках пользователю? Какую информацию должен получать пользователь? Как «перевести» часто невразумительные сообщения об ошибках, выдаваемые базой данных, на язык, понятный пользователям?
С этими общими вопросами тесно связаны более конкретные проблемы:
- Следует ли включать раздел обработки исключений в каждый блок PL/SQL?
- Следует ли включать раздел обработки исключений только в блок верхнего уровня или внешние блоки?
- Как организовать управление транзакциями при возникновении ошибок? Сложность обработки исключений отчасти связана с тем, что на все эти вопросы не существует единственно правильного ответа. Все зависит (по крайней мере частично) от архитектуры приложения и режима его использования (например, пакетное выполнение или транзакции, управляемые пользователем). Но если вы сможете ответить на эти вопросы для своего приложения, я рекомендую «запрограммировать» стратегию и правила обработки ошибок в стандартном пакете (см. далее «Стандартизация обработки ошибок»).
Некоторые общие принципы, которые стоит принять во внимание:
- Когда в коде происходит ошибка, получите как можно больше информации о контексте ее возникновения. Избыток информации — лучше, чем ее нехватка. Далее исключение можно передавать во внешние блоки, собирая дополнительную информацию по мере продвижения.
- Избегайте применения обработчиков вида
WHEN
ошибкаTHEN NULL
; (или еще хуже,WHEN OTHERS THEN NULL;
). Возможно, для написания такого хода у вас имеются веские причины, но вы должны твердо понимать, что это именно то, что вам нужно, и документировать такое использование, чтобы о нем знали другие. - Там, где это возможно, используйте механизмы обработки ошибок PL/SQL по умолчанию. Избегайте написания программ, возвращающих коды состояния управляющей среде или вызывающим блокам. Применять коды состояния следует только в одной ситуации: если управляющая среда не способна корректно обрабатывать ошибки Oracle (в таком случае стоит подумать о смене управляющей среды!).
Стандартизация обработки разных типов исключений
Исключение всегда свидетельствует о критической ситуации? Вовсе нет. Некоторые исключения (например, ORA-00600) сообщают о том, что в базе данных возникли очень серьезные низкоуровневые проблемы. Другие исключения, такие как NO_DATA_FOUND
, встречаются так часто, что мы воспринимаем их не как ошибки, а как условную логическую конструкцию («Если строка не существует, то выполнить следующие действия…»). Нужно ли различать эти категории исключений?
Коллеги-программисты научил меня очень полезной системе классификации исключений.
- Преднамеренные исключения. Архитектура кода сознательно использует особенности работы исключения. Это означает, что разработчик должен предвидеть исключение и запрограммировать его обработку. Пример —
UTL_FILE
.GET_LINE
. - Нежелательные исключения. Происходит ошибка, но ее возможность была предусмотрена заранее. Возможно, исключение даже не свидетельствует о возникновении проблемы. Пример команда
SELECT INTO
, инициирующая исключениеNO_DATA_FOUND
. - Непредвиденные исключения. Серьезные ошибки, указывающие на возникновение проблемы в приложении. Пример — команда
SELECT INTO
, которая должна вернуть строку для заданного первичного ключа, но вместо этого инициирует исключениеTOO_MANY
ROWS
.
Давайте поближе познакомимся с примерами всех категорий, а затем поговорим о том, какую пользу вы можете извлечь из знания этих категорий.
Преднамеренные исключения
Разработчики PL/SQL могут использовать процедуру UTL_FILE
.GET_LINE
для чтения содержимого файла по строкам. Когда GET_LINE
выходит за границу файла, инициируется исключение NO_DATA_FOUND
. Так работает эта процедура. Итак, если я хочу прочитать все содержимое файла и сделать «что-то полезное», программа может выглядеть так:
PROCEDURE read_file_and_do_stuff (
dir_in IN VARCHAR2, file_in IN VARCHAR2
)
IS
l_file UTL_FILE.file_type;
l_line VARCHAR2 (32767);
BEGIN
l_file := UTL_FILE.fopen (dir_in, file_in, 'R', max_linesize => 32767);
LOOP
UTL_FILE.get_line (l_file, l_line);
do_stuff;
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
UTL_FILE.fclose (l_file);
more_stuff_here;
END;
У этого цикла есть одна особенность: он не содержит команды EXIT
. Кроме того, в разделе исключений выполняется дополнительная логика приложения (more_stuff_here
). Цикл можно переписать в следующем виде:
LOOP
BEGIN
UTL_FILE.get_line (l_file, l_line);
do_stuff;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
EXIT;
END;
END LOOP;
UTL_FILE.flcose (l_file);
more_stuff_here;
Теперь цикл содержит команду EXIT
, но код стал более громоздким.
Подобные конструкции приходится использовать при работе с кодом, намеренно инициирующем исключения в своей архитектуре. Дополнительная информация о том, как следует поступать в подобных случаях, приводится в следующих разделах.
Нежелательные и непредвиденные исключения
Я рассматриваю эти две категории вместе, потому что приводимые примеры (NO_DATA_FOUND
и TOO_MANY_ROWS
) тесно связаны между собой. Предположим, я хочу написать функцию, возвращающую полное имя работника (в формате фамилия запятая имя) для заданного значения первичного ключа. Проще всего это сделать так:
FUNCTION fullname (
employee_id_in IN employees.employee_id%TYPE
)
RETURN VARCHAR2
IS
retval VARCHAR2 (32767);
BEGIN
SELECT last_name || ',' || first_name
INTO retval
FROM employees
WHERE employee_id = employee_id_in;
RETURN retval;
END fullname;
Если вызвать эту программу с кодом работника, отсутствующим в таблице, база данных инициирует исключение NO_DATA_FOUND
. Если же вызвать ее с кодом работника, встречающимся в нескольких строках таблицы, будет инициировано исключение TOO_MANY_ROWS
. Один запрос, два разных исключения — нужно ли рассматривать их одинаково? Вероятно, нет. Описывают ли эти два исключения похожие группы проблем? Давайте посмотрим:
NO_DATA_FOUND
— совпадение не найдено. Исключение может указывать на наличие серьезной проблемы, но не обязательно. Возможно, в большинстве обращений к базе данных совпадение не будет обнаруживаться, и я буду вставлять в базу данные нового работника. В общем, исключение нежелательно, но в данном случае оно даже не указывает на возникновение ошибки.TOO_MANY_ROWS
— в базе данных возникла серьезная проблема с ограничением первичного ключа. Трудно представить себе ситуацию, в которой это было бы нормально или просто «нежелательно». Нет, нужно прервать работу программы и привлечь внимание пользователя к совершенно непредвиденной, критической ошибке.
Как извлечь пользу из этой классификации
Надеюсь, вы согласитесь, что такая классификация полезна. Приступая к построению нового приложения, постарайтесь по возможности определиться со стандартным подходом, который будет применяться вами (и всеми остальными участниками группы) для каждого типа исключений. Затем для каждого исключения (которое необходимо обработать или хотя бы учитывать заранее при написании кода) решите, к какой категории относится, и примените уже согласованный подход. Все это поможет сделать ваш код более последовательным, и повысит эффективность вашей работы. Приведу несколько рекомендаций для трех типов исключений.
- Преднамеренные исключения. Пишите код, учитывающий возможность возникновения таких исключений. Прежде всего постарайтесь избежать размещения логики приложения в разделе исключений. Раздел исключений должен содержать только код, относящийся к обработке ошибки: сохранение информации об ошибке в журнале, повторное инициирование исключения и т. д. Программисты не ожидают увидеть логику приложения в разделе исключений, поэтому им будет намного труднее разобраться в таком коде и обеспечить его сопровождение.
- Нежелательные исключения. Если в каких-то обстоятельствах пользователь кода, инициировавшего исключения, не будет интерпретировать ситуацию как ошибку, не передавайте исключения наружу без обработки. Вместо этого верните значение или флаг состояния, показывающий, что исключение было обработано. Далее пользователь программы может сам решить, должна ли программа завершиться с ошибкой. А еще лучше — почему бы не разрешить стороне, вызывающей вашу программу, решить, нужно ли инициировать исключение, и если не нужно — какое значение должно передаваться для обозначения возникшего исключения?
- Непредвиденные исключения. А теперь начинается самое неприятное. Все непредвиденные ошибки должны быть сохранены в журнале с максимумом возможной контекстной информации, которая поможет понять причины возникновения ошибки. Затем программа должна завершиться с необработанным исключением (обычно тем же), инициированным из программы; для этого можно воспользоваться командой
RAISE
. Исключение заставит вызвавшую программу прервать работу и обработать ошибку.
Коды ошибок, связанные с конкретным приложением
Используя команду RAISE_APPLICATION_ERROR
для инициирования ошибок, относящихся к конкретному приложению, вы несете полную ответственность за управление кодами ошибок и сообщениями. Это быстро становится хлопотным и непростым делом («Так, какой бы код мне выбрать? Пожалуй, –20 774 — вроде бы такого еще не было?»).
Чтобы упростить управление кодами ошибок и предоставить последовательный интерфейс, через который разработчики смогут обрабатывать серверные ошибки, постройте таблицу со всеми используемыми кодами ошибок −20 NNN, сопутствующими именами исключений и сообщениями об ошибках.
Разработчик может просмотреть уже определенные ошибки на экране и выбрать ту из них, которая лучше всего подходит для конкретной ситуации.
Также можно попытаться полностью избегать диапазон −20 NNN для ошибок приложений. Почему бы не воспользоваться положительными числами? Из положительного цело-численного поддиапазона Oracle использует только 1 и 100. Теоретически возможно, что когда-нибудь Oracle будет использовать и другие положительные числа, но это весьма маловероятно. В распоряжении разработчиков остается великое множество кодов ошибок.
В частности, я пошел по этому пути при проектировании Quest Error Manager (QEM) — бесплатной программы управления ошибками. В Quest Error Manager вы можете определять свои ошибки в специальной таблице. Ошибка определяется именем и/ или кодом. Коды ошибок могут быть положительными или отрицательными. Если код ошибки положителен, при инициировании исключения QEM использует команду RAISE_APPLICATION_ERROR
для инициирования обобщенного исключения (обычно −20 000). Информация о текущем коде ошибки приложения встраивается в сообщение об ошибке, которое может быть расшифровано программой-получателем.
Упрощенная реализация этого подхода представлена в пакете обработки ошибок errpkg. pkg
, описанном в следующем разделе блога.
Стандартизация обработки ошибок
Обязательным элементом любого профессионально написанного приложения является надежная и согласованная схема обработки ошибок. Согласованность в этом вопросе важна как для пользователя, так и для разработчика. Если при возникновении ошибки пользователю предоставляется понятная, хорошо структурированная информация, он сможет более подробно рассказать об ошибке службе поддержки и будет более уверенно чувствовать себя при работе с приложением. Если приложение всегда обрабатывает и протоколирует ошибки определенным образом, программистам, занимающимся его поддержкой и сопровождением, будет легче их найти и устранить.
Все кажется вполне очевидным, не так ли? К сожалению, на практике (и особенно в больших группах разработчиков) все происходит несколько иначе. Очень часто каждый разработчик идет своим путем, следуя личным принципам и приемам, сохраняя информацию в произвольно выбранном формате и т. д. Одним словом, без стандартизации отладка и сопровождение приложений оборачиваются сущим кошмаром. Рассмотрим типичный пример:
EXCEPTION
WHEN NO_DATA_FOUND
THEN
v_msg := 'Нет компании с идентификатором '||TO_CHAR (v_id);
v_err := SQLCODE;
v_prog := 'fixdebt';
INSERT INTO errlog VALUES
(v_err,v_msg,v_prog,SYSDATE,USER);
WHEN OTHERS
THEN
v_err := SQLCODE;
v_msg := SQLERRM;
v_prog := 'fixdebt';
INSERT INTO errlog VALUES
(v_err,v_msg,v_prog,SYSDATE,USER);
RAISE;
На первый взгляд код выглядит вполне разумно. Если компания с заданным идентификатором не найдена, мы получаем значение SQLCODE
, задаем имя программы и сообщение и записываем строку с информацией об ошибке в таблицу ошибок. Выполнение родительского блока продолжается, поскольку ошибка не критична. Если происходит любая другая ошибка, получаем ее код и соответствующее сообщение, задаем имя программы и записываем строку с информацией об ошибке в таблицу ошибок, а затем передаем исключение в родительский блок, чтобы остановить его выполнение (поскольку неизвестно, насколько критична эта ошибка).
Что же здесь не так? Чтобы подробно объяснить суть проблемы, достаточно взглянуть на код. В нем жестко закодированы все действия по обработке ошибок. В результате (1) код получается слишком объемистым, (2) его придется полностью переписывать при изменении схемы обработки ошибок. Обратите внимание еще и на тот факт, что информация об ошибке записывается в таблицу базы данных. Это означает, что запись в журнале становится частью логической транзакции. И если потребуется выполнить откат транзакции, записи в журнале ошибок будут утеряны.
Существует несколько способов избежать потери информации: можно записывать данные в файл или использовать автономные транзакции для сохранения журнала вне основной транзакции. Но как бы то ни было, код в случае его изменения придется исправлять в сотнях разных мест.
А теперь посмотрите, как этот же раздел исключений оформляется при использовании стандартизированного пакета:
EXCEPTION
WHEN NO_DATA_FOUND
THEN
errpkg.record_and_continue (
SQLCODE, 'Нет компании с идентификатором ' || TO_CHAR (v_id));
WHEN OTHERS
THEN
errpkg.record_and_stop;
END;
Такой пакет обработки ошибок скрывает все подробности реализации; вы просто решаете, какая из процедур-обработчиков должна использоваться в конкретном случае, просматривая спецификацию пакета. Если требуется сохранить информацию об ошибке и продолжить работу, вызывается программа record_and_continue
. Если же нужно сохранить информацию об ошибке и прервать выполнение родительского блока, вызывается программа record_and_stop
. Мы не знаем, как эти программы сохраняют информацию об ошибке, как они останавливают работу родительского блока, то есть передают исключение, но для нас это и не важно. Главное, что все происходит так, как определено стандартами приложения.
Это дает вам возможность уделить больше времени разработке более интересных элементов приложения и не заниматься административной рутиной.
Имеется файл errpkg.pkg
с прототипом стандартизированного пакета обработки ошибок. Правда, прежде чем использовать его в приложениях, вам необходимо будет завершить его реализацию; это поможет составить ясное представление о том, как конструируются подобные утилиты.
Вы также можете воспользоваться намного более мощным (и тоже бесплатным) средством обработки ошибок Quest Error Manager. Важнейшая концепция, заложенная в основу QEM, заключается в возможности перехвата и протоколирования экземпляров ошибок, не только ошибок Oracle. QEM состоит из пакета PL/SQL и четырех таблиц для хранения информации об ошибках, возникающих в приложениях.
Работа с «объектами» исключений
Реализация типа данных EXCEPTION
в Oracle имеет свои ограничения, о которых было рассказано выше. Исключение состоит из идентификатора (имени), с которым связывается числовой код и сообщение. Исключение можно инициировать, его можно обработать… и все. Теперь представьте, как та же ситуация выглядит в Java: все ошибки являются производными от единого класса Exception
. Этот класс можно расширить, дополняя его новыми характеристиками, которые вы хотите отслеживать (стек ошибок, контекстные данные и т. д.). Объект, созданный на основе класса Exception, ничем не отличается от любых других объектов Java. Разумеется, он может передаваться в аргументах методов.
PL/SQL не позволяет делать ничего подобного со своими исключениями. Впрочем, этот факт не мешает вам реализовать свой «объект» исключения. Для этого можно воспользоваться объектными типами Oracle или реляционной таблицей, содержащей информацию об ошибке. Независимо от выбранной реализации очень важно различать определение ошибки (код ошибки –1403, имя «данные не найдены», причина — «неявный курсор не нашел ни одной записи») и ее конкретный экземпляр (я попытался найти компанию с указанным именем, ни одной строки не найдено). Иначе говоря, существует всего одно определение исключения NO_DATA_FOUND
, которое может существовать во множестве экземпляров. Oracle не различает эти два представления ошибки, но для нас это безусловно необходимо.
Пример простой иерархии объектов исключений продемонстрирует этот момент. Начнем с базового объектного типа всех исключений:
CREATE TYPE exception_t AS OBJECT (
name VARCHAR2(100),
code INTEGER,
description VARCHAR2(4000),
help_text VARCHAR2(4000),
recommendation VARCHAR2(4000),
error_stack CLOB,
call_stack CLOB,
created_on DATE,
created_by VARCHAR2(100)
)
NOT FINAL;
/
Затем базовый тип исключения расширяется для ошибок динамического SQL посредством добавления атрибута sql_string. При обработке ошибок динамического SQL очень важно сохранить строку, создавшую проблемы, для анализа в будущем:
CREATE TYPE dynsql_exception_t UNDER exception_t (
sql_string CLOB )
NOT FINAL;
/
А вот другой подтип exception_t
, на этот раз относящийся к конкретной сущности приложения — работнику. Исключение, инициируемое для ошибок, относящихся к работникам, будет включать идентификатор работника и внешний ключ нарушенного правила:
CREATE TYPE employee_exception_t UNDER exception_t (
employee_id INTEGER,
rule_id INTEGER );
/
Полная спецификация иерархии объектов ошибок включает методы супертипа исключения, предназначенные для вывода информации об ошибках или ее записи в репозиторий. Вы можете самостоятельно завершить иерархию, определенную в файле exception.ot
.
Если вы не хотите работать с объектными типами, попробуйте использовать подход, использованный мной в QEM: я определяю таблицу определений ошибок (Q$ERROR
) и другую таблицу экземпляров ошибок (Q$ERROR_INSTANCE
), которая содержит информацию о конкретных экземплярах ошибок. Все контекстные данные экземпляра ошибки сохраняются в таблице Q$ERROR_CONTEXT
.
Пример кода, который мог бы быть написан для QEM API:
WHEN DUP_VAL_ON_INDEX
THEN
q$error_manager.register_error (
error_name_in => 'DUPLICATE-VALUE'
,err_instance_id_out => l_err_instance_id
);
q$error_manager.add_context (
err_instance_id_in => l_err_instance_id
,name_in => 'TABLE_NAME', value_in => 'EMPLOYEES'
);
q$error_manager.add_context (
err_instance_id_in => l_err_instance_id
,name_in => 'KEY_VALUE', value_in => l_employee_id
);
q$error_manager.raise_error_instance (
err_instance_id_in => l_err_instance_id);
END;
Если ошибка повторяющегося значения была вызвана ограничением уникального имени, я получаю идентификатор экземпляра ошибки DUPLICATE-VALUE
. (Да, все верно: я использую имена ошибок, полностью обходя все проблемы, связанные с номерами ошибок.) Затем я добавляю контекстную информацию экземпляра (имя таблицы и значение первичного ключа, вызвавшее проблему). В завершение инициируется экземпляр ошибки, в результате чего исключение передается в следующий наружный блок.
По аналогии с передачей данных из приложения в репозиторий ошибок через API, вы также можете получить информацию об ошибке при помощи процедуры get_error_info
.
Пример:
BEGIN
run_my_application_code;
EXCEPTION
WHEN OTHERS
THEN
DECLARE
l_error q$error_manager.error_info_rt;
BEGIN
q$error_manager.get_error_info (l_error);
DBMS_OUTPUT.put_line ('');
DBMS_OUTPUT.put_line ('Error in DEPT_SAL Procedure:');
DBMS_OUTPUT.put_line ('Code = ' || l_error.code);
DBMS_OUTPUT.put_line ('Name = ' || l_error.NAME);
DBMS_OUTPUT.put_line ('Text = ' || l_error.text);
DBMS_OUTPUT.put_line ('Error Stack = ' || l_error.error_stack);
END;
END;
Это лишь два из многих способов преодоления ограничений типа EXCEPTION
в PL/SQL. Мораль: ничто не заставляет вас мириться с ситуацией по умолчанию, при которой с экземпляром ошибки связывается только код и сообщение.
Создание стандартного шаблона для обобщенной обработки ошибок
Невозможность передачи исключений программе сильно усложняет совместное использование разделов обработки ошибок в разных блоках PL/SQL. Одну и ту же логику обработчика нередко приходится записывать снова и снова, особенно при работе с конкретными функциональными областями — скажем, файловым вводом/ выводом с UTL_FILE
. В таких ситуациях стоит выделить время на создание шаблонов обработчиков.
Давайте поближе познакомимся с UTL_FILE
. До выхода Oracle9i Database Release 2 в спецификации пакета UTL_FILE
определялся набор исключений. Однако компания Oracle не стала предоставлять коды этих исключений через директиву EXCEPTION_INIT
. А без обработки исключений UTL_FILE
по имени SQLCODE
не сможет разобраться, что пошло не так. Вероятно, в такой ситуации для программ UTL_FILE
можно создать шаблон, часть которого выглядит так:
DECLARE
l_file_id UTL_FILE.file_type;
PROCEDURE cleanup (file_in IN OUT UTL_FILE.file_type
,err_in IN VARCHAR2 := NULL)
IS
BEGIN
UTL_FILE.fclose (file_in);
IF err_in IS NOT NULL
THEN
DBMS_OUTPUT.put_line ('Обнаружена ошибка UTL_FILE:');
DBMS_OUTPUT.put_line (err_in);
END IF;
END cleanup;
BEGIN
-- Здесь размещается тело программы.
-- Перед выходом необходимо прибрать за собой ...
cleanup (l_file_id);
EXCEPTION
WHEN UTL_FILE.invalid_path
THEN
cleanup (l_file_id, 'invalid_path');
RAISE;
WHEN UTL_FILE.invalid_mode
THEN
cleanup (l_file_id, 'invalid_mode');
RAISE;
END;
Основные элементы шаблона:
- Программа выполнения завершающих действий, пригодная для повторного использования; гарантирует, что текущий файл будет закрыт до потери дескриптора файла.
- Преобразование именованного исключения в строку, которую можно сохранить в журнале или вывести на экран, чтобы пользователь точно знал, какая ошибка была инициирована.
Рассмотрим еще один пример шаблона, который удобно использовать при работе с UTL_FILE
. В Oracle9i Database Release 2 появилась программа FREMOVE
для удаления файлов. Пакет UTL_FILE
предоставляет исключение DELETE_FAILED
, инициируемое тогда, когда FREMOVE
не удается удалить файл. После тестирования программы я обнаружил, что FREMOVE
может инициировать несколько возможных исключений, в числе которых:
UTL_FILE
.INVALID_OPERATION
— удаляемый файл не существует.UTL_FILE
.DELETE_FAILED
— у вас (или у процесса Oracle) недостаточно привилегий для удаления файла, или попытка завершилась неудачей по другой причине.
Начиная с Oracle9i Database Release 2, UTL_FILE
назначает коды ошибок всем своим исключениям, но вы все равно должны проследить за тем, чтобы при возникновении ошибки файлы были закрыты, и организовать последовательную обработку ошибок.
Итак, при использовании UTL_FILE
.FREMOVE
следует включать раздел обработчика исключения, который различает эти две ошибки:
BEGIN
UTL_FILE.fremove (dir, filename);
EXCEPTION
WHEN UTL_FILE.delete_failed
THEN
DBMS_OUTPUT.put_line (
'Ошибка при попытке удаления: ' || filename || ' в ' || dir);
-- Выполнение соответствующих действий...
WHEN UTL_FILE.invalid_operation
THEN
DBMS_OUTPUT.put_line (
'Не удалось найти и удалить: ' || filename || ' в ' || dir);
-- Выполнение соответствующих действий...
END;
Оптимальная организация обработки ошибок в PL/SQL
Без унифицированной качественной методологии обработки ошибок очень трудно написать приложение, которое было бы удобным в использовании и одновременно простым в отладке.
Архитектура обработки ошибок в Oracle PL/SQL предоставляет очень гибкие средства для определения, инициирования и обработки ошибок. Однако у нее имеются свои ограничения, вследствие чего встроенную функциональность обычно приходится дополнять таблицами и кодами ошибок, специфическими для конкретного приложения.
Для решения проблемы обработки ошибок рекомендуется предпринять следующие действия:
- Тщательно разберитесь в системе инициирования и обработки ошибок в PL/SQL. Далеко не во ее аспекты интуитивно понятны. Простейший пример: исключение, инициированное в секции объявлений, не будет обрабатываться секцией исключений текущего блока.
- Выберите общую схему обработки ошибок в вашем приложении. Где и как будут обрабатываться ошибки? Какая информация об ошибке будет сохраняться и как это будет сделано? Как исключения будут передаваться в управляющую среду? Как будут обрабатываться намеренные и непредвиденные ошибки?
- Постройте стандартную инфраструктуру, которая будет использоваться всеми разработчиками проекта. Инфраструктура должна включать таблицы, пакеты и, возможно, объектные типы, а также четко определенный процесс использования всех перечисленных элементов. Не останавливайтесь на ограничениях PL/ SQL. Найдите обходные пути, расширяя модель обработки ошибок.
- Создайте шаблоны, которые могут использоваться всеми участниками вашей группы. Всегда проще следовать готовому стандарту, чем самостоятельно писать код обработки ошибок.
Жду отклика на статью. Что понравилось? Что нет?
Вас заинтересует / Intresting for you:
Как отлавливать ошибки в Oracle (PLSQL) EXCEPTION,SQLERRM,SQLCODE
Осваиваем Oracle и PL/SQL
Маленькое руководство по отлавливанию ошибок в Oracle PLSQL.
Описание как использовать в Oracle (PLSQL) функции SQLERRM и SQLCODE для отлова ошибок EXCEPTION, с описанием синтаксиса и примером.
Функция SQLERRM возвращает сообщение об ошибке связанное с последним возникшим исключением (ошибкой).
Функция SQLERRM — не имеет параметров.
Функция SQLCODE возвращает код ошибки связанный с последним возникшим исключением (ошибкой)
Функция SQLERRM — не имеет параметров.
Обычно обработка исключений EXCEPTION выглядит следующим образом:
EXCEPTION
WHEN наименование_ошибки_1 THEN
[statements]
WHEN наименование_ошибки_2 THEN
[statements]
WHEN наименование_ошибки_N THEN
[statements]
WHEN OTHERS THEN
[statements]
END [наименование_процедуры];
Вы можете использовать функции SQLERRM и SQLCODE для вызова сообщения об ошибке например таким образом:
EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20001,'Произошла ошибка - '||SQLCODE||' -ERROR- '||SQLERRM);
END;
-- В данном случае появится всплывающее сообщение.
Или вы можете сохранить сообщение об ошибке в таблицу таким образом:
EXCEPTION
WHEN OTHERS THEN
err_code := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 200);
INSERT INTO error_log_table (error_time, error_number, error_message)
VALUES (sysdate, err_code, err_msg);
END;
--В данном случае ошибка будет помещена в таблицу error_log_table
Варианты основных возможных ошибок:
DUP_VAL_ON_INDEX
ORA-00001
При попытке произвести вставку INSERT или изменение UPDATE данных которое создает дублирующую запись нарушающую уникальный индекс (unique index).
TIMEOUT_ON_RESOURCE
ORA-00051
Происходит когда ресурс над которым производится операция заблокирован и произошел сброс по таймауту.
TRANSACTION_BACKED_OUT
ORA-00061
Произошёл частичный откат транзакции.
INVALID_CURSOR
ORA-01001
Попытка использовать курсор которого не существует. Может происходить если вы пытаетесь использовать FETCH курсор или закрыть CLOSE курсор до того как вы этот курсор открыли OPEN.
NOT_LOGGED_ON
ORA-01012
Попытка произвести действия не залогинившись.
LOGIN_DENIED
ORA-01017
Неудачная попытка залогиниться, в доступе отказано, не верный пользователь или пароль.
NO_DATA_FOUND
ORA-01403
Что то из перечисленного: Попытка произвести вставку SELECT INTO несуществующего набора значений (select — ничего не возвращает). Попытка доступа к неинициализированной строке/записи в таблице. Попытка чтения записи после окончания файла при помощи пакета UTL_FILE.
TOO_MANY_ROWS
ORA-01422
Попытка вставить значение в переменную при помощи SELECT INTO и select вернул более чем одно значение.
ZERO_DIVIDE
ORA-01476
Попытка деления на ноль.
INVALID_NUMBER
ORA-01722
Попытка выполнить SQL запрос который производит конвертацию строки (STRING) в число (NUMBER) при этом такое преобразование невозможно.
STORAGE_ERROR
ORA-06500
Либо нехватка памяти, либо ошибка в памяти.
PROGRAM_ERROR
ORA-06501
Внутренняя программная ошибка рекомендуется с такой ошибкой обращаться в службу поддержки Oracle.
VALUE_ERROR
ORA-06502
Попытка выполнить операцию конвертации данных которая закончилась с ошибкой (например: округление, преобразование типов, и т.п.).
CURSOR_ALREADY_OPEN
ORA-06511
Вы пытаетесь открыть курсор который уже открыт.
Вот пожалуй и всё.
Oracle
PLSQL
SQL
EXCEPTION
SQLERRM
SQLCODE
ошибки
программирование
- The Need for Error Handling
- Error Handling Alternatives
- Using Status Variables when MODE={ANSI|ANSI14}
- Using the SQL Communications Area
- Using the Oracle Communications Area
An application program must anticipate runtime errors and attempt to recover from them. This chapter provides an in-depth discussion of error reporting and recovery. You learn how to handle warnings and errors using the status variables SQLCODE, SQLSTATE, and SQLCA (SQL Communications Area), and the WHENEVER statement. You also learn how to diagnose problems using the status variable ORACA (Oracle Communications Area). The following topics are discussed:
- the need for error handling
- error handling alternatives
- using status variables when MODE={ANSI|ANSI14}
- using the SQL Communications Area
- using the Oracle Communications Area
The Need for Error Handling
A significant part of every application program must be devoted to error handling. The main benefit of error handling is that it allows your program to continue operating in the presence of errors. Errors arise from design faults, coding mistakes, hardware failures, invalid user input, and many other sources
You cannot anticipate all possible errors, but you can plan to handle certain kinds of errors meaningful to your program. For the Oracle Precompilers, error handling means detecting and recovering from SQL statement execution errors.
You can also prepare to handle warnings such as «value truncated» and status changes such as «end of data.» It is especially important to check for error and warning conditions after every data manipulation statement, because an INSERT, UPDATE, or DELETE statement might fail before processing all eligible rows in a table.
Error Handling Alternatives
The Oracle Precompilers provide four status variables that serve as error handling mechanisms:
- SQLCODE (SQLCOD in Pro*FORTRAN)
- SQLSTATE (SQLSTA in Pro*FORTRAN)
- SQLCA (using the WHENEVER statement)
- ORACA
The MODE option (described ) governs ANSI/ISO compliance. The availability of the SQLCODE, SQLSTATE, and SQLCA variables depends on the MODE setting. You can declare and use the ORACA variable regardless of the MODE setting. For more information, see «Using the Oracle Communications Area»
.
When MODE={ORACLE|ANSI13}, you must declare the SQLCA status variable. SQLCODE and SQLSTATE declarations are accepted (not recommended) but are not recognized as status variables. For more information, see «Using the SQL Communications Area» .
When MODE={ANSI|ANSI14}, you can use any one, two, or all three of the SQLCODE, SQLSTATE, and SQLCA variables. To determine which variable (or variable combination) is best for your application, see «Using Status Variables when MODE={ANSI|ANSI14}» .
SQLCODE and SQLSTATE
With Release 1.5 of the Oracle Precompilers, the SQLCODE status variable was introduced as the SQL89 standard ANSI/ISO error reporting mechanism. The SQL92 standard listed SQLCODE as a deprecated feature and defined a new status variable, SQLSTATE (introduced with Release 1.6 of the Oracle Precompilers), as the preferred ANSI/ISO error reporting mechanism.
SQLCODE stores error codes and the «not found» condition. It is retained only for compatibility with SQL89 and is likely to be removed from future versions of the standard.
Unlike SQLCODE, SQLSTATE stores error and warning codes and uses a standardized coding scheme. After executing a SQL statement, the Oracle server returns a status code to the SQLSTATE variable currently in scope. The status code indicates whether a SQL statement executed successfully or raised an exception (error or warning condition). To promote interoperability (the ability of systems to exchange information easily), SQL92 predefines all the common SQL exceptions.
SQLCA
The SQLCA is a record-like, host-language data structure. Oracle updates the SQLCA after every executable SQL statement. (SQLCA values are undefined after a declarative statement.) By checking Oracle return codes stored in the SQLCA, your program can determine the outcome of a SQL statement. This can be done in two ways:
- implicit checking with the WHENEVER statement
- explicit checking of SQLCA variables
You can use WHENEVER statements, code explicit checks on SQLCA variables, or do both. Generally, using WHENEVER statements is preferable because it is easier, more portable, and ANSI-compliant.
ORACA
When more information is needed about runtime errors than the SQLCA provides, you can use the ORACA, which contains cursor statistics, SQL statement data, option settings, and system statistics.
The ORACA is optional and can be declared regardless of the MODE setting. For more information about the ORACA status variable, see «Using the Oracle Communications Area» .
Using Status Variables when MODE={ANSI|ANSI14}
When MODE={ANSI|ANSI14}, you must declare at least one — you may declare two or all three — of the following status variables:
- SQLCODE
- SQLSTATE
- SQLCA
In Pro*COBOL, you cannot declare SQLCODE if SQLCA is declared. Likewise, you cannot declare SQLCA if SQLCODE is declared. The field in the SQLCA data structure that stores the error code for Pro*COBOL is also called SQLCODE, so errors will occur if both status variables are declared.
Your program can get the outcome of the most recent executable SQL statement by checking SQLCODE and/or SQLSTATE explicitly with your own code after executable SQL and PL/SQL statements. Your program can also check SQLCA implicitly (with the WHENEVER SQLERROR and WHENEVER SQLWARNING statements) or it can check the SQLCA variables explicitly.
Note: When MODE={ORACLE|ANSI13}, you must declare the SQLCA status variable. For more information, see «Using the SQL Communications Area» .
Some Historical Information
The treatment of status variables and variable combinations by the Oracle Precompilers has evolved beginning with Release 1.5.
Release 1.5
The Oracle Precompilers, Release 1.5, presumed there was a status variable SQLCODE whether or not it was declared in a Declare Section; in fact, the precompiler never bothered to note whether there was a declaration for SQLCODE or not — it just presumed one existed. SQLCA would be used as a status variable if and only if there was an INCLUDE of the SQLCA.
Release 1.6
Beginning with Oracle Precompilers, Release 1.6, the precompilers no longer presume that there is a SQLCODE status variable and it is not required. The precompiler requires that at least one of SQLCA, SQLCODE, or SQLSTATE be declared.
SQLCODE is recognized as a status variable if and only if at least one of the following criteria is satisfied:
- It is declared in a Declare Section with exactly the right datatype.
- The precompiler finds no other status variable.
If the precompiler finds a SQLSTATE declaration (of exactly the right type of course) in a Declare Section or finds an INCLUDE of the SQLCA, it will not presume SQLCODE is declared.
Release 1.7
Because Release 1.5 of the Oracle Precompilers allowed the SQLCODE variable to be declared outside of a Declare Section while also declaring SQLCA, precompilers Release 1.6 and greater are presented with a compatibility problem. A new option, ASSUME_SQLCODE={YES|NO} (default NO), was added to fix this in Release 1.6.7 and is documented as a new feature in Release 1.7.
When ASSUME_SQLCODE=YES, and when SQLSTATE and/or SQLCA (Pro*FORTRAN only) are declared as status variables, the precompiler presumes SQLCODE is declared whether or not it is declared in a Declare Section or of the proper type. This causes Releases 1.6.7 and later to act like Release 1.5 in this regard. For information about the precompiler option ASSUME_SQLCODE, see «ASSUME_SQLCODE» .
Declaring Status Variables
This section describes how to declare SQLCODE and SQLSTATE. For information about declaring the SQLCA status variable, see «Declaring the SQLCA» .
Declaring SQLCODE
SQLCODE (SQLCOD in Pro*FORTRAN) must be declared as a 4-byte integer variable either inside or outside the Declare Section, as shown in Table 8 — 1.
Language | SQLCODE Declaration |
---|---|
COBOL | SQLCODE PIC S9(9) COMP. |
FORTRAN | INTEGER*4 SQLCOD |
Table 8 — 1. SQLCODE Declarations
If declared outside the Declare Section, SQLCODE is recognized as a status variable if only if ASSUME_SQLCODE=YES. SQLCODE declarations are ignored when MODE={ORACLE|ANSI13}.
Warning: In Pro*COBOL source files, do not declare SQLCODE if SQLCA is declared. Likewise, do not declare SQLCA if SQLCODE is declared. The status variable declared by the SQLCA structure is also called SQLCODE, so errors will occur if both error-reporting mechanisms are used.
With host languages that allow both local and global declarations, you can declare more than one SQLCODE variable. Access to a local SQLCODE is limited by its scope within your program. After every SQL operation, Oracle returns a status code to the SQLCODE currently in scope. So, your program can learn the outcome of the most recent SQL operation by checking SQLCODE explicitly, or implicitly with the WHENEVER statement.
When you declare SQLCODE instead of the SQLCA in a particular compilation unit, the precompiler allocates an internal SQLCA for that unit. Your host program cannot access the internal SQLCA. If you declare the SQLCA and SQLCODE (not supported in Pro*COBOL), Oracle returns the same status code to both after every SQL operation.
Declaring SQLSTATE
SQLSTATE (SQLSTA in Pro*FORTRAN) must be declared as a five-character alphanumeric string inside the Declare Section, as shown in Table 8 — 2. Declaring the SQLCA is optional.
Language | SQLSTATE Declaration |
---|---|
COBOL | SQLSTATE PIC X(5). |
FORTRAN | CHARACTER*5 SQLSTA |
Table 8 — 2. SQLSTATE Declarations
When MODE={ORACLE|ANSI13}, declarations of the SQLSTATE variable are ignored.
Status Variable Combinations
When MODE={ANSI|ANSI14}, the behavior of the status variables depends on the following:
- which variables are declared
- declaration placement (inside or outside the Declare Section)
- ASSUME_SQLCODE setting
Table 8 — 3
and Table 8 — 4 describe the resulting behavior of each status variable combination when ASSUME_SQLCODE=NO and when ASSUME_SQLCODE=YES, respectively.
Declare Section (IN/OUT/ —) SQLCODE SQLSTATE SQLCA |
Behavior | ||
---|---|---|---|
OUT | — | — | SQLCODE is declared and is presumed to be a status variable. |
OUT | — | OUT | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, SQLCA is declared as a status variable, and SQLCODE is declared but is not recognized as a status variable. |
OUT | — | IN | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, this status variable configuration is not supported. |
OUT | OUT | — | SQLCODE is declared and is presumed to be a status variable, and SQLSTATE is declared but is not recognized as a status variable. |
OUT | OUT | OUT | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, SQLCA is declared as a status variable, and SQLCODE and SQLSTATE are declared but are not recognized as status variables. |
OUT | OUT | IN | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, this status variable configuration is not supported. |
OUT | IN | — | SQLSTATE is declared as a status variable, and SQLCODE is declared but is not recognized as a status variable. |
OUT | IN | OUT | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, SQLSTATE and SQLCA are declared as status variables, and SQLCODE is declared but is not recognized as a status variable. |
OUT | IN | IN | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, this status variable configuration is not supported. |
IN | — | — | SQLCODE is declared as a status variable. |
IN | — | OUT | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, SQLCODE and SQLCA are declared as a status variables. |
IN | — | IN | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, this status variable configuration is not supported. |
IN | OUT | — | SQLCODE is declared as a status variable, and SQLSTATE is declared but not as a status variable. |
IN | OUT | OUT | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, SQLCODE and SQLCA are declared as a status variables, and SQLSTATE is declared but is not recognized as a status variable. |
IN | OUT | IN | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, this status variable configuration is not supported. |
IN | IN | — | SQLCODE and SQLSTATE are declared as a status variables. |
IN | IN | OUT | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, SQLCODE, SQLSTATE, and SQLCA are declared as a status variables. |
IN | IN | IN | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, this status variable configuration is not supported. |
— | — | — | This status variable configuration is not supported. |
— | — | OUT | SQLCA is declared as a status variable. |
— | — | IN | In Pro*COBOL, SQLCA is declared as a status host variable. In Pro*FORTRAN, this status variable configuration is not supported. |
— | OUT | — | This status variable configuration is not supported. |
— | OUT | OUT | SQLCA is declared as a status variable, and SQLSTATE is declared but is not recognized as a status variable. |
— | OUT | IN | In Pro*COBOL, SQLCA is declared as a status host variable, and SQLSTATE is declared but is not recognized as a status variable. In Pro*FORTRAN, this status variable configuration is not supported. |
— | IN | — | SQLSTATE is declared as a status variable. |
— | IN | OUT | SQLSTATE and SQLCA are declared as status variables. |
— | IN | IN | In Pro*COBOL, SQLSTATE and SQLCA are declared as status host variables. In Pro*FORTRAN, this status variable configuration is not supported. |
Table 8 — 3. Status Variable Behavior with ASSUME_SQLCODE=NO and MODE=ANSI|ANSI14
Declare Section (IN/OUT/ —) SQLCODE SQLSTATE SQLCA |
Behavior | ||
---|---|---|---|
OUT | — | — | SQLCODE is declared and is presumed to be a status variable. |
OUT | — | OUT | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, SQLCA is declared as a status variable, and SQLCODE is declared and is presumed to be a status variable. |
OUT | — | IN | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, this status variable configuration is not supported. |
OUT | OUT | — | SQLCODE is declared and is presumed to be a status variable, and SQLSTATE is declared but is not recognized as a status variable. |
OUT | OUT | OUT | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, SQLCA is declared as a status variable, SQLCODE is declared and is presumed to be a status variable, and SQLSTATE is declared but is not recognized as status variable. |
OUT | OUT | IN | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, this status variable configuration is not supported. |
OUT | IN | — | SQLSTATE is declared as a status variable, and SQLCODE is declared and is presumed to be a status variable. |
OUT | IN | OUT | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, SQLSTATE and SQLCA are declared as status variables, and SQLCODE is declared and is presumed to be a status variable. |
OUT | IN | IN | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, this status variable configuration is not supported. |
IN | — | — | SQLCODE is declared as a status variable. |
IN | — | OUT | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, SQLCODE and SQLCA are declared as a status variables. |
IN | — | IN | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, this status variable configuration is not supported. |
IN | OUT | — | SQLCODE is declared as a status variable, and SQLSTATE is declared but not as a status variable. |
IN | OUT | OUT | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, SQLCODE and SQLCA are declared as a status variables, and SQLSTATE is declared but is not recognized as a status variable. |
IN | OUT | IN | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, this status variable configuration is not supported. |
IN | IN | — | SQLCODE and SQLSTATE are declared as a status variables. |
IN | IN | OUT | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, SQLCODE, SQLSTATE, and SQLCA are declared as a status variables. |
IN | IN | IN | In Pro*COBOL, this status variable configuration is not supported. In Pro*FORTRAN, this status variable configuration is not supported. |
— — — — — — — — — | — — — OUT OUT OUT IN IN IN | — OUT IN — OUT IN — OUT IN | These status variable configurations are not supported. SQLCODE must be declared either inside or outside the Declare Section when ASSUME_SQLCODE=YES. |
Table 8 — 4. Status Variable Behavior with ASSUME_SQLCODE=YES and MODE=ANSI|ANSI14
Status Variable Values
This section describes the values for the SQLCODE and SQLSTATE status variables. For information about the SQLCA status variable, see «Key Components of Error Reporting» .
SQLCODE Values
After every SQL operation, Oracle returns a status code to the SQLCODE variable currently in scope. The status code, which indicates the outcome of the SQL operation, can be any of the following numbers:
0
Oracle executed the SQL statement without detecting an error or exception.
> 0
Oracle executed the statement but detected an exception. This occurs when Oracle cannot find a row that meets the condition in your WHERE clause or when a SELECT INTO or FETCH returns no rows.
When MODE={ANSI|ANSI14|ANSI13}, +100 is returned to SQLCODE after an INSERT of no rows. This can happen when a subquery returns no rows to process.
< 0
Oracle did not execute the statement because of a database, system, network, or application error. Such errors can be fatal. When they occur, the current transaction should, in most cases, be rolled back. Negative return codes correspond to error codes listed in Oracle7 Server Messages.
You can learn the outcome of the most recent SQL operation by checking SQLCODE explicitly with your own code or implicitly with the WHENEVER statement.
When you declare SQLCODE instead of the SQLCA in a particular precompilation unit, the precompiler allocates an internal SQLCA for that unit. Your host program cannot access the internal SQLCA. If you declare the SQLCA and SQLCODE (Pro*FORTRAN only), Oracle returns the same status code to both after every SQL operation.
Note: When MODE={ORACLE|ANSI13}, declarations of SQLCODE are ignored.
SQLSTATE Values
SQLSTATE status codes consist of a two-character class code followed by a three-character subclass code. Aside from class code 00 (successful completion), the class code denotes a category of exceptions. Aside from subclass code 000 (not applicable), the subclass code denotes a specific exception within that category. For example, the SQLSTATE value `22012′ consists of class code 22 (data exception) and subclass code 012 (division by zero).
Each of the five characters in a SQLSTATE value is a digit (0..9) or an uppercase Latin letter (A..Z). Class codes that begin with a digit in the range 0..4 or a letter in the range A..H are reserved for predefined conditions (those defined in SQL92). All other class codes are reserved for implementation-defined conditions. Within predefined classes, subclass codes that begin with a digit in the range 0..4 or a letter in the range A..H are reserved for predefined subconditions. All other subclass codes are reserved for implementation-defined subconditions. Figure 8 — 1 shows the coding scheme.
Text description of the illustration image010.gif. Figure 8 — 1. SQLSTATE Coding Scheme
Table 8 — 5 shows the classes predefined by SQL92.
Class | Condition |
---|---|
00 | successful completion |
01 | warning |
02 | no data |
07 | dynamic SQL error |
08 | connection exception |
0A | feature not supported |
21 | cardinality violation |
22 | data exception |
23 | integrity constraint violation |
24 | invalid cursor state |
25 | invalid transaction state |
26 | invalid SQL statement name |
27 | triggered data change violation |
28 | invalid authorization specification |
2A | direct SQL syntax error or access rule violation |
2B | dependent privilege descriptors still exist |
2C | invalid character set name |
2D | invalid transaction termination |
2E | invalid connection name |
33 | invalid SQL descriptor name |
34 | invalid cursor name |
35 | invalid condition number |
37 | dynamic SQL syntax error or access rule violation |
3C | ambiguous cursor name |
3D | invalid catalog name |
3F | invalid schema name |
40 | transaction rollback |
42 | syntax error or access rule violation |
44 | with check option violation |
HZ | remote database access |
Table 8 — 5. Predefined Classes
Note: The class code HZ is reserved for conditions defined in International Standard ISO/IEC DIS 9579-2, Remote Database Access.
Table 8 — 6 shows how Oracle errors map to SQLSTATE status codes. In some cases, several Oracle errors map to the status code. In other cases, no Oracle error maps to the status code (so the last column is empty). Status codes in the range 60000 .. 99999 are implementation-defined.
Code | Condition | Oracle Error |
---|---|---|
00000 | successful completion | ORA-00000 |
01000 | warning | |
01001 | cursor operation conflict | |
01002 | disconnect error | |
01003 | null value eliminated in set function | |
01004 | string data — right truncation | |
01005 | insufficient item descriptor areas | |
01006 | privilege not revoked | |
01007 | privilege not granted | |
01008 | implicit zero-bit padding | |
01009 | search condition too long for info schema | |
0100A | query expression too long for info schema | |
02000 | no data | ORA-01095 ORA-01403 |
07000 | dynamic SQL error | |
07001 | using clause does not match parameter specs | |
07002 | using clause does not match target specs | |
07003 | cursor specification cannot be executed | |
07004 | using clause required for dynamic parameters | |
07005 | prepared statement not a cursor specification | |
07006 | restricted datatype attribute violation | |
07007 | using clause required for result fields | |
07008 | invalid descriptor count | SQL-02126 |
07009 | invalid descriptor index | |
08000 | connection exception | |
08001 | SQL client unable to establish SQL connection | |
08002 | connection name in use | |
08003 | connection does not exist | SQL-02121 |
08004 | SQL server rejected SQL connection | |
08006 | connection failure | |
08007 | transaction resolution unknown | |
0A000 | feature not supported | ORA-03000 .. 03099 |
0A001 | multiple server transactions | |
21000 | cardinality violation | ORA-01427 SQL-02112 |
22000 | data exception | |
22001 | string data — right truncation | ORA-01401 ORA-01406 |
22002 | null value — no indicator parameter | ORA-01405 SQL-02124 |
22003 | numeric value out of range | ORA-01426 ORA-01438 ORA-01455 ORA-01457 |
22005 | error in assignment | |
22007 | invalid datetime format | |
22008 | datetime field overflow | ORA-01800 .. 01899 |
22009 | invalid time zone displacement value | |
22011 | substring error | |
22012 | division by zero | ORA-01476 |
22015 | interval field overflow | |
22018 | invalid character value for cast | |
22019 | invalid escape character | ORA-00911 ORA-01425 |
22021 | character not in repertoire | |
22022 | indicator overflow | ORA-01411 |
22023 | invalid parameter value | ORA-01025 ORA-01488 ORA-04000 .. 04019 |
22024 | unterminated C string | ORA-01479 .. 01480 |
22025 | invalid escape sequence | ORA-01424 |
22026 | string data — length mismatch | |
22027 | trim error | |
23000 | integrity constraint violation | ORA-00001 ORA-02290 .. 02299 |
24000 | invalid cursor state | ORA-01001 .. 01003 ORA-01410 ORA-08006 SQL-02114 SQL-02117 SQL-02118 SQL-02122 |
25000 | invalid transaction state | |
26000 | invalid SQL statement name | |
27000 | triggered data change violation | |
28000 | invalid authorization specification | |
2A000 | direct SQL syntax error or access rule violation | |
2B000 | dependent privilege descriptors still exist | |
2C000 | invalid character set name | |
2D000 | invalid transaction termination | |
2E000 | invalid connection name | |
33000 | invalid SQL descriptor name | |
34000 | invalid cursor name | |
35000 | invalid condition number | |
37000 | dynamic SQL syntax error or access rule violation | |
3C000 | ambiguous cursor name | |
3D000 | invalid catalog name | |
3F000 | invalid schema name | |
40000 | transaction rollback | ORA-02091 .. 02092 |
40001 | serialization failure | |
40002 | integrity constraint violation | |
40003 | statement completion unknown | |
42000 | syntax error or access rule violation | ORA-00022 ORA-00251 ORA-00900 .. 00999 ORA-01031 ORA-01490 .. 01493 ORA-01700 .. 01799 ORA-01900 .. 02099 ORA-02140 .. 02289 ORA-02420 .. 02424 ORA-02450 .. 02499 ORA-03276 .. 03299 ORA-04040 .. 04059 ORA-04070 .. 04099 |
44000 | with check option violation | ORA-01402 |
60000 | system errors | ORA-00370 .. 00429 ORA-00600 .. 00899 ORA-06430 .. 06449 ORA-07200 .. 07999 ORA-09700 .. 09999 |
61000 | resource error | ORA-00018 .. 00035 ORA-00050 .. 00068 ORA-02376 .. 02399 ORA-04020 .. 04039 |
62000 | multi-threaded server and detached process errors | ORA-00100 .. 00120 ORA-00440 .. 00569 |
63000 | Oracle*XA and two-task interface errors | ORA-00150 .. 00159 SQL-02128 ORA-02700 .. 02899 ORA-03100 .. 03199 ORA-06200 .. 06249 SQL-02128 |
64000 | control file, database file, and redo file errors; archival and media recovery errors | ORA-00200 .. 00369 ORA-01100 .. 01250 |
65000 | PL/SQL errors | ORA-06500 .. 06599 |
66000 | SQL*Net driver errors | ORA-06000 .. 06149 ORA-06250 .. 06429 ORA-06600 .. 06999 ORA-12100 .. 12299 ORA-12500 .. 12599 |
67000 | licensing errors | ORA-00430 .. 00439 |
69000 | SQL*Connect errors | ORA-00570 .. 00599 ORA-07000 .. 07199 |
72000 | SQL execute phase errors | ORA-01000 .. 01099 ORA-01400 .. 01489 ORA-01495 .. 01499 ORA-01500 .. 01699 ORA-02400 .. 02419 ORA-02425 .. 02449 ORA-04060 .. 04069 ORA-08000 .. 08190 ORA-12000 .. 12019 ORA-12300 .. 12499 ORA-12700 .. 21999 |
82100 | out of memory (could not allocate) | SQL-02100 |
82101 | inconsistent cursor cache: unit cursor/global cursor mismatch | SQL-02101 |
82102 | inconsistent cursor cache: no global cursor entry | SQL-02102 |
82103 | inconsistent cursor cache: out of range cursor cache reference | SQL-02103 |
82104 | inconsistent host cache: no cursor cache available | SQL-02104 |
82105 | inconsistent cursor cache: global cursor not found | SQL-02105 |
82106 | inconsistent cursor cache: invalid Oracle cursor number | SQL-02106 |
82107 | program too old for runtime library | SQL-02107 |
82108 | invalid descriptor passed to runtime library | SQL-02108 |
82109 | inconsistent host cache: host reference is out of range | SQL-02109 |
82110 | inconsistent host cache: invalid host cache entry type | SQL-02110 |
82111 | heap consistency error | SQL-02111 |
82112 | unable to open message file | SQL-02113 |
82113 | code generation internal consistency failed | SQL-02115 |
82114 | reentrant code generator gave invalid context | SQL-02116 |
82115 | invalid hstdef argument | SQL-02119 |
82116 | first and second arguments to sqlrcn both null | SQL-02120 |
82117 | invalid OPEN or PREPARE for this connection | SQL-02122 |
82118 | application context not found | SQL-02123 |
82119 | connect error; can’t get error text | SQL-02125 |
82120 | precompiler/SQLLIB version mismatch. | SQL-02127 |
82121 | FETCHed number of bytes is odd | SQL-02129 |
82122 | EXEC TOOLS interface is not available | SQL-02130 |
82123 | runtime context in use | SQL-02131 |
82124 | unable to allocate runtime context | SQL-02131 |
82125 | unable to initialize process for use with threads | SQL-02133 |
82126 | invalid runtime context | SQL-02134 |
90000 | debug events | ORA-10000 .. 10999 |
99999 | catch all | all others |
HZ000 | remote database access |
Table 8 — 6. SQLSTATE Codes
Using the SQL Communications Area
The SQL Communications area (SQLCA) is a record-like data structure. Its fields contain error, warning, and status information updated by Oracle whenever a SQL statement is executed. Thus, the SQLCA always reflects the outcome of the most recent SQL operation. To determine the outcome, you can check variables in the SQLCA.
In host languages that allow both local and global declarations, your program can have more than one SQLCA. For example, it might have one global SQLCA and several local ones. Access to a local SQLCA is limited by its scope within the program. Oracle returns information only to the «active» SQLCA.
Note: When your application uses SQL*Net to access a combination of local and remote databases concurrently, all the databases write to one SQLCA. There is not a different SQLCA for each database. For more information, see «Concurrent Logons» .
When MODE={ORACLE|ANSI13}, the SQLCA is required; if the SQLCA is not declared, compile-time errors will occur. The SQLCA is optional when MODE={ANSI|ANSI14}, but you cannot use the WHENEVER SQLWARNING statement without declaring SQLCA. So, if you want to use the WHENEVER SQLWARNING statement, you must declare the SQLCA.
Note: If you declare SQLCODE instead of the SQLCA in a particular compilation unit, the precompiler allocates an internal SQLCA for that unit. Your host program cannot access the internal SQLCA. If you declare the SQLCA and SQLCODE (Pro*FORTRAN only), Oracle returns the same status code to both after every SQL operation.
When MODE={ANSI|ANSI14}, you must declare either SQLSTATE (see «Declaring SQLSTATE» ) or SQLCODE (see «Declaring SQLCODE»
) or both. The SQLSTATE status variable supports the SQLSTATE status variable specified by the SQL92 standard. You can use the SQLSTATE status variable with or without SQLCODE. See Table 8 — 3 and Table 8 — 4 for more information.
Declaring the SQLCA
To declare the SQLCA, simply include it (using an EXEC SQL INCLUDE statement) in your host-language source file as follows:
* Include the Oracle Communications Area (ORACA). EXEC SQL INCLUDE ORACA EXEC SQL INCLUDE SQLCA;
The SQLCA is used if and only if there is an INCLUDE of the SQLCA.
When you precompile your program, the INCLUDE SQLCA statement is replaced by several variable declarations that allow Oracle to communicate with the program.
Declaring the SQLCA in Pro*COBOL
In Pro*COBOL, it makes no difference whether the INCLUDE is inside or outside of a Declare Section. For more information about declaring the SQLCA in Pro*COBOL, see the Pro*COBOL Supplement to the Oracle Precompilers Guide.
Declaring the SQLCA in Pro*FORTRAN
In Pro*FORTRAN, the SQLCA must be declared outside the Declare Section, because it is a COMMON block. Furthermore, the SQLCA must come before the CONNECT statement and the first executable FORTRAN statement.
You must declare the SQLCA in each subroutine and function that contains SQL statements. Every time a SQL statement in one of the subroutines or functions is executed, Oracle updates the SQLCA held in the COMMON block.
Ordinarily, only the order and datatypes of variables in a COMMON-list matter, not their names. However, you cannot rename the SQLCA variables because the precompiler generates code that refers to them. Thus, all declarations of the SQLCA must be identical. For more information about declaring the SQLCA in Pro*FORTRAN, see the Pro*FORTRAN Supplement to the Oracle Precompilers Guide.
What’s in the SQLCA?
The SQLCA contains the following runtime information about the outcome of SQL statements:
- Oracle error codes
- warning flags
- event information
- rows-processed count
- diagnostics
Figure 8 — 2
shows all the variables in the SQLCA. To see the SQLCA structure and variable names in a particular host language, refer to your supplement to this Guide.
Text description of the illustration image011.gif. Figure 8 — 2. SQLCA Variables
Key Components of Error Reporting
Error reporting depends on variables in the SQLCA. This section highlights the key components of error reporting. The next section takes a close look at the SQLCA.
Status Codes
Every executable SQL statement returns a status code to the SQLCA variable SQLCODE, which you can check implicitly with the WHENEVER statement or explicitly with your own code.
Status codes can be zero, less than zero, or greater than zero. See «SQLCODE» for complete SQLCODE descriptions.
Warning Flags
Warning flags are returned in the SQLCA variables SQLWARN(0) through SQLWARN(7), which you can check implicitly or explicitly. These warning flags are useful for runtime conditions not considered errors by Oracle. For example, when DBMS=V6, if an indicator variable is available, Oracle signals a warning after assigning a truncated column value to a host variable. (If no indicator variable is available, Oracle issues an error message.)
Rows-Processed Count
The number of rows processed by the most recently executed SQL statement is returned in the SQLCA variable SQLERRD(3), which you can check explicitly.
Speaking strictly, this variable is not for error reporting, but it can help you avoid mistakes. For example, suppose you expect to delete about ten rows from a table. After the deletion, you check SQLERRD(3) and find that 75 rows were processed. To be safe, you might want to roll back the deletion and examine the search condition in your WHERE clause.
Parse Error Offset
Before executing a SQL statement, Oracle must parse it, that is, examine it to make sure it follows syntax rules and refers to valid database objects. If Oracle finds an error, an offset is stored in the SQLCA variable SQLERRD(5), which you can check explicitly. The offset specifies the character position in the SQL statement at which the parse error begins. The first character occupies position zero. For example, if the offset is 9, the parse error begins at the tenth character.
By default, static SQL statements are checked for syntactic errors at precompile time. So, SQLERRD(5) is most useful for debugging dynamic SQL statements, which your program accepts or builds at run time.
Parse errors arise from missing, misplaced, or misspelled keywords, invalid options, nonexistent tables, and the like. For example, the dynamic SQL statement
UPDATE EMP SET JIB = :job_title WHERE EMPNO = :emp_number
causes the parse error
ORA-00904: invalid column name
because the column name JOB is misspelled. The value of SQLERRD(5) is 15 because the erroneous column name JIB begins at the sixteenth character.
If your SQL statement does not cause a parse error, Oracle sets SQLERRD(5) to zero. Oracle also sets SQLERRD(5) to zero if a parse error begins at the first character (which occupies position zero). So, check SQLERRD(5) only if SQLCODE is negative, which means that an error has occurred.
Error Message Text
The error code and message for Oracle errors are available in the SQLCA variable SQLERRMC. At most, the first 70 characters of text are stored. To get the full text of messages longer than 70 characters, you use the SQLGLM function. See «Getting the Full Text of Error Messages» .
SQLCA Structure
This section describes the structure of the SQLCA, its fields, and the values they can store.
SQLCAID
This string field is initialized to «SQLCA» to identify the SQL Communications Area.
SQLCABC
This integer field holds the length, in bytes, of the SQLCA structure.
SQLCODE
This integer field holds the status code of the most recently executed SQL statement. The status code, which indicates the outcome of the SQL operation, can be any of the following numbers:
0
Oracle executed the statement without detecting an error or exception.
> 0
Oracle executed the statement but detected an exception. This occurs when Oracle cannot find a row that meets your WHERE-clause search condition or when a SELECT INTO or FETCH returns no rows.
< 0
When MODE={ANSI|ANSI14|ANSI13}, +100 is returned to SQLCODE after an INSERT of no rows. This can happen when a subquery returns no rows to process.
Oracle did not execute the statement because of a database, system, network, or application error. Such errors can be fatal. When they occur, the current transaction should, in most cases, be rolled back.
Negative return codes correspond to error codes listed in Oracle7 Server Messages.
SQLERRM
This subrecord contains the following two fields:
SQLERRML
This integer field holds the length of the message text stored in SQLERRMC.
SQLERRMC
This string field holds the message text for the error code stored in SQLCODE and can store up to 70 characters. For the full text of messages longer than 70 characters, use the SQLGLM function.
Verify SQLCODE is negative
before you reference SQLERRMC. If you reference SQLERRMC when SQLCODE is zero, you get the message text associated with a prior SQL statement.
SQLERRP
This string field is reserved for future use.
SQLERRD
This array of binary integers has six elements. Descriptions of the fields in SQLERRD (called SQLERD in FORTRAN) follow:
SQLERRD(1)
This field is reserved for future use.
SQLERRD(2)
This field is reserved for future use.
SQLERRD(3)
This field holds the number of rows processed by the most recently executed SQL statement. However, if the SQL statement failed, the value of SQLERRD(3) is undefined, with one exception. If the error occurred during an array operation, processing stops at the row that caused the error, so SQLERRD(3) gives the number of rows processed successfully.
The rows-processed count is zeroed after an OPEN statement and incremented after a FETCH statement. For the EXECUTE, INSERT, UPDATE, DELETE, and SELECT INTO statements, the count reflects the number of rows processed successfully. The count does
not include rows processed by an update or delete cascade. For example, if 20 rows are deleted because they meet WHERE-clause criteria, and 5 more rows are deleted because they now (after the primary delete) violate column constraints, the count is 20 not 25.
SQLERRD(4)
This field is reserved for future use.
SQLERRD(5)
This field holds an offset that specifies the character position at which a parse error begins in the most recently executed SQL statement. The first character occupies position zero.
SQLERRD(6)
This field is reserved for future use.
SQLWARN
This array of single characters has eight elements. They are used as warning flags. Oracle sets a flag by assigning it a «W» (for warning) character value. The flags warn of exceptional conditions.
For example, a warning flag is set when Oracle assigns a truncated column value to an output host variable.
Note: While Figure 8 — 2 illustrates SQLWARN as an array, it is implemented in Pro*COBOL as a group item with elementary PIC X items named SQLWARN0 through SQLWARN7. The Pro*FORTRAN implementation is composed of the LOGICAL variables, SQLWN0 through SQLWN7.
Descriptions of the fields in SQLWARN follow:
SQLWARN(0)
This flag is set if another warning flag is set.
SQLWARN(1)
This flag is set if a truncated column value was assigned to an output host variable. This applies only to character data. Oracle truncates certain numeric data without setting a warning or returning a negative SQLCODE value.
To find out if a column value was truncated and by how much, check the indicator variable associated with the output host variable. The (positive) integer returned by an indicator variable is the original length of the column value. You can increase the length of the host variable accordingly.
SQLWARN(2)
This flag is set if one or more nulls were ignored in the evaluation of a SQL group function such as AVG, COUNT, or MAX. This behavior is expected because, except for COUNT(*), all group functions ignore nulls. If necessary, you can use the SQL function NVL to temporarily assign values (zeros, for example) to the null column entries.
SQLWARN(3)
This flag is set if the number of columns in a query select list does not equal the number of host variables in the INTO clause of the SELECT or FETCH statement. The number of items returned is the lesser of the two.
SQLWARN(4)
This flag is set if every row in a table was processed by an UPDATE or DELETE statement without a WHERE clause. An update or deletion is called unconditional if no search condition restricts the number of rows processed. Such updates and deletions are unusual, so Oracle sets this warning flag. That way, you can roll back the transaction if necessary
SQLWARN(5)
This flag is set when an EXEC SQL CREATE {PROCEDURE|FUNCTION|PACKAGE|PACKAGE BODY} statement fails because of a PL/SQL compilation error.
SQLWARN(6)
This flag is no longer in use.
SQLWARN(7)
This flag is no longer in use.
SQLEXT
This string field is reserved for future use.
PL/SQL Considerations
When your precompiler program executes an embedded PL/SQL block, not all fields in the SQLCA are set. For example, if the block fetches several rows, the rows-processed count, SQLERRD(3), is set to 1, not the actual number of rows fetched. So, you should rely only on the SQLCODE and SQLERRM fields in the SQLCA after executing a PL/SQL block.
Getting the Full Text of Error Messages
The SQLCA can accommodate error messages up to 70 characters long. To get the full text of longer (or nested) error messages, you need the SQLGLM function. If connected to Oracle, you can call SQLGLM using the syntax
SQLGLM(message_buffer, buffer_size, message_length);
where:
message_buffer
is the text buffer in which you want Oracle to store the error message (Oracle blank-pads to the end of this buffer).
buffer_size
is an integer variable that specifies the maximum size of the buffer in bytes.
message_length
is an integer variable in which Oracle stores the actual length of the error message.
The maximum length of an Oracle error message is 512 characters including the error code, nested messages, and message inserts such as table and column names. The maximum length of an error message returned by SQLGLM depends on the value you specify for buffer_size.
In the following example, you call SQLGLM to get an error message of up to 100 characters in length:
-- declare variables for function call msg_buffer CHARACTER(100); buf_size INTEGER; msg_length INTEGER; set buf_size = 100; EXEC SQL WHENEVER SQLERROR DO sql_error; -- other statements ROUTINE sql_error BEGIN -- get full text of error message SQLGLM(msg_buffer, buf_size, msg_length); display contents of msg_buffer; exit program with an error END sql_error;
Notice that SQLGLM is called only when a SQL error has occurred. Always make sure SQLCODE is negative before calling SQLGLM. If you call SQLGLM when SQLCODE is zero, you get the message text associated with a prior SQL statement.
Using the WHENEVER Statement
By default, precompiled programs ignore Oracle error and warning conditions and continue processing if possible. To perform automatic condition checking and error handling, use the WHENEVER statement.
With the WHENEVER statement you can specify actions to be taken when Oracle detects an error, warning condition, or «not found» condition. These actions include continuing with the next statement, calling a routine, branching to a labeled statement, or stopping.
You code the WHENEVER statement using the following syntax:
EXEC SQL WHENEVER <condition> <action>;
You can have Oracle automatically check the SQLCA for any of the following conditions.
SQLWARNING
SQLWARN(0) is set because Oracle returned a warning (one of the warning flags, SQLWARN(1) through SQLWARN(7), is also set) or SQLCODE has a positive value other than +1403. For example, SQLWARN(1) is set when Oracle assigns a truncated column value to an output host variable.
Declaring the SQLCA is optional when MODE={ANSI|ANSI14}. To use WHENEVER SQLWARNING, however, you must declare the SQLCA.
SQLERROR
SQLCODE has a negative value because Oracle returned an error.
NOT FOUND
SQLCODE has a value of +1403 (+100 when MODE={ANSI|ANSI14| ANSI13}), because Oracle could not find a row that meets the search condition of a WHERE clause, or a SELECT INTO or FETCH returned no rows. When MODE={ANSI|ANSI14|ANSI13}, +100 is returned to SQLCODE after an INSERT of no rows.
When Oracle detects one of the preceding conditions, you can have your program take any of the following actions.
CONTINUE
Your program continues to run with the next statement if possible. This is the default action, equivalent to not using the WHENEVER statement. You can use it to «turn off» condition checking.
DO
Your program transfers control to an internal routine. When the end of the routine is reached, control transfers to the statement that follows the failed SQL statement.
A routine is any functional program unit that can be invoked such as a COBOL paragraph or FORTRAN subroutine. In this context, separately compiled programs, such as COBOL subroutines, are not routines.
The usual rules for entering and exiting a routine apply. However, passing parameters to the routine is not allowed. Furthermore, the routine must not return a value.
The parameter routine_call is a host language invocation, as in
EXEC SQL -- COBOL WHENEVER <condition> DO PERFORM <paragraph_name> -- COBOL END-EXEC. -- COBOL
or
EXEC SQL -- FORTRAN WHENEVER <condition> DO CALL <subroutine_name> -- FORTRAN
GOTO
Your program branches to a labeled statement.
STOP
Your program stops running and uncommitted work is rolled back.
Be careful. The STOP action displays no messages before logging off Oracle. In Pascal, the STOP action is illegal because Pascal has no equivalent command.
Some Examples
If you want your program to
- go to close_cursor if a «no data found» condition occurs,
- continue with the next statement if a warning occurs, and
- go to error_handler if an error occurs
simply code the following WHENEVER statements before the first executable SQL statement:
EXEC SQL WHENEVER NOT FOUND GOTO close_cursor; EXEC SQL WHENEVER SQLWARNING CONTINUE; EXEC SQL WHENEVER SQLERROR GOTO error_handler;
The following Pro*C example uses WHENEVER…DO statements to handle specific errors:
EXEC SQL WHENEVER SQLERROR DO handle_insert_error; EXEC SQL INSERT INTO EMP (EMPNO, ENAME, DEPTNO) VALUES (:emp_number, :emp_name, :dept_number); EXEC SQL WHENEVER SQLERROR DO handle_delete_error; EXEC SQL DELETE FROM DEPT WHERE DEPTNO = :dept_number; ... ROUTINE handle_insert_error; BEGIN IF sqlca.sqlcode = -1 THEN -- duplicate key value ... ELSEIF sqlca.sqlcode = -1401 THEN -- value too large ... ENDIF; ... END; ROUTINE handle_delete_error; BEGIN IF sqlca.sqlerrd(3) = 0 THEN -- no rows deleted ... ELSE ... ENDIF; ... END; ...
Notice how the procedures check variables in the SQLCA to determine a course of action.
Scope
Because WHENEVER is a declarative statement, its scope is positional, not logical. It tests all executable SQL statements that follow it in the source file, not in the flow of program logic. So, code the WHENEVER statement before the first executable SQL statement you want to test.
A WHENEVER statement stays in effect until superseded by another WHENEVER statement checking for the same condition.
In the example below, the first WHENEVER SQLERROR statement is superseded by a second, and so applies only to the CONNECT statement. The second WHENEVER SQLERROR statement applies to both the UPDATE and DROP statements, despite the flow of control from step1 to step3.
step1: EXEC SQL WHENEVER SQLERROR STOP; EXEC SQL CONNECT :username IDENTIFIED BY :password; ... GOTO step3; step2: EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL UPDATE EMP SET SAL = SAL * 1.10; ... step3: EXEC SQL DROP INDEX EMP_INDEX; ...
Guidelines
The following guidelines will help you avoid some common pitfalls.
Placing the Statements. In general, code a WHENEVER statement before the first executable SQL statement in your program. This ensures that all ensuing errors are trapped because WHENEVER statements stay in effect to the end of a file.
Handling End-of-Data Conditions. Your program should be prepared to handle an end-of-data condition when using a cursor to fetch rows. If a FETCH returns no data, the program should branch to a labeled section of code where a CLOSE command is issued, as follows:
SQL WHENEVER NOT FOUND GOTO no_more; ... no_more: ... EXEC SQL CLOSE my_cursor; ...
Avoiding Infinite Loops. If a WHENEVER SQLERROR GOTO statement branches to an error handling routine that includes an executable SQL statement, your program might enter an infinite loop if the SQL statement fails with an error. You can avoid this by coding WHENEVER SQLERROR CONTINUE before the SQL statement, as shown in the following example:
EXEC SQL WHENEVER SQLERROR GOTO sql_error; ... sql_error: EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL ROLLBACK WORK RELEASE; ...
Without the WHENEVER SQLERROR CONTINUE statement, a ROLLBACK error would invoke the routine again, starting an infinite loop.
Careless use of WHENEVER can cause problems. For example, the following code enters an infinite loop if the DELETE statement sets NOT FOUND because no rows meet the search condition:
-- improper use of WHENEVER ... EXEC SQL WHENEVER NOT FOUND GOTO no_more; LOOP EXEC SQL FETCH emp_cursor INTO :emp_name, :salary; ... ENDLOOP; no_more: EXEC SQL DELETE FROM EMP WHERE EMPNO = :emp_number; ...
In the next example, you handle the NOT FOUND condition properly by resetting the GOTO target:
-- proper use of WHENEVER ... EXEC SQL WHENEVER NOT FOUND GOTO no_more; LOOP EXEC SQL FETCH emp_cursor INTO :emp_name, :salary; ... ENDLOOP; no_more: EXEC SQL WHENEVER NOT FOUND GOTO no_match; EXEC SQL DELETE FROM EMP WHERE EMPNO = :emp_number; ... no_match: ...
Maintaining Addressability. With host languages that allow local as well as global identifiers, make sure all SQL statements governed by a WHENEVER GOTO statement can branch to the GOTO label. The following code results in a compile-time error because labelA in FUNC1 is not within the scope of the INSERT statement in FUNC2:
FUNC1 BEGIN EXEC SQL WHENEVER SQLERROR GOTO labelA; EXEC SQL DELETE FROM EMP WHERE DEPTNO = :dept_number; ... labelA: ... END; FUNC2 BEGIN EXEC SQL INSERT INTO EMP (JOB) VALUES (:job_title); ... END;
The label to which a WHENEVER GOTO statement branches must be in the same precompilation file as the statement.
Returning after an Error. If your program must return after handling an error, use the DO routine_call action. Alternatively, you can test the value of SQLCODE, as shown in the following example:
EXEC SQL UPDATE EMP SET SAL = SAL * 1.10; IF sqlca.sqlcode < 0 THEN -- handle error EXEC SQL DROP INDEX EMP_INDEX; ...
Just make sure no WHENEVER GOTO or WHENEVER STOP statement is active.
Getting the Text of SQL Statements
In many precompiler applications, it is convenient to know the text of the statement being processed, its length, and the SQL command (such as INSERT or SELECT) that it contains. This is especially true for applications that use dynamic SQL.
The routine SQLGLS, which is part of the SQLLIB runtime library, returns the following information:
- the text of the most recently parsed SQL statement
- the length of the statement
- a function code (see Table 8 —
for the SQL command used in the statement
You can call SQLGLS after issuing a static SQL statement. With dynamic SQL Method 1, you can call SQLGLS after the SQL statement is executed. With dynamic SQL Method 2, 3, or 4, you can call SQLGLS after the statement is prepared.
To call SQLGLS, you use the following syntax:
SQLGLS(SQLSTM, STMLEN, SQLFC)
Table 8 — 7 shows the host-language datatypes available for the parameters in the SQLGLS argument list.
Parameter | Language | Datatype |
---|---|---|
SQLSTM | COBOL | PIC X(n) |
FORTRAN | CHARACTER*n | |
STMLEN, SQLFC | COBOL | PIC S9(9) COMP |
FORTRAN | INTEGER*4 |
Table 8 — 7. Parameter Datatypes
All parameters must be passed by reference. This is usually the default parameter passing convention; you need not take special action.
The parameter SQLSTM is a blank-padded (not null-terminated) character buffer that holds the returned text of the SQL statement. Your program must statically declare the buffer or dynamically allocate memory for it.
The length parameter STMLEN is a four-byte integer. Before calling SQLGLS, set this parameter to the actual size (in bytes) of the SQLSTM buffer. When SQLGLS returns, the SQLSTM buffer contains the SQL statement text blank padded to the length of the buffer. STMLEN returns the actual number of bytes in the returned statement text, not counting the blank padding. However, STMLEN returns a zero if an error occurred.
Some possible errors follow:
- No SQL statement was parsed.
- You passed an invalid parameter (for example, a negative length value).
- An internal exception occurred in SQLLIB.
The parameter SQLFC is a four-byte integer that returns the SQL function code for the SQL command in the statement. Table 8 — 8 shows the function code for each SQL command.
SQLGLS does not return statements that contain the following commands:
- CONNECT
- COMMIT
- ROLLBACK
- RELEASE
- FETCH
There are no SQL function codes for these statements.
Code | SQL Function | Code | SQL Function |
---|---|---|---|
01 | CREATE TABLE | 39 | AUDIT |
02 | SET ROLE | 40 | NOAUDIT |
03 | INSERT | 41 | ALTER INDEX |
04 | SELECT | 42 | CREATE EXTERNAL DATABASE |
05 | UPDATE | 43 | DROP EXTERNAL DATABASE |
06 | DROP ROLE | 44 | CREATE DATABASE |
07 | DROP VIEW | 45 | ALTER DATABASE |
08 | DROP TABLE | 46 | CREATE ROLLBACK SEGMENT |
09 | DELETE | 47 | ALTER ROLLBACK SEGMENT |
10 | CREATE VIEW | 48 | DROP ROLLBACK SEGMENT |
11 | DROP USER | 49 | CREATE TABLESPACE |
12 | CREATE ROLE | 50 | ALTER TABLESPACE |
13 | CREATE SEQUENCE | 51 | DROP TABLESPACE |
14 | ALTER SEQUENCE | 52 | ALTER SESSION |
15 | (not used) | 53 | ALTER USER |
16 | DROP SEQUENCE | 54 | COMMIT |
17 | CREATE SCHEMA | 55 | ROLLBACK |
18 | CREATE CLUSTER | 56 | SAVEPOINT |
19 | CREATE USER | 57 | CREATE CONTROL FILE |
20 | CREATE INDEX | 58 | ALTER TRACING |
21 | DROP INDEX | 59 | CREATE TRIGGER |
22 | DROP CLUSTER | 60 | ALTER TRIGGER |
23 | VALIDATE INDEX | 61 | DROP TRIGGER |
24 | CREATE PROCEDURE | 62 | ANALYZE TABLE |
25 | ALTER PROCEDURE | 63 | ANALYZE INDEX |
26 | ALTER TABLE | 64 | ANALYZE CLUSTER |
27 | EXPLAIN | 65 | CREATE PROFILE |
28 | GRANT | 66 | DROP PROFILE |
29 | REVOKE | 67 | ALTER PROFILE |
30 | CREATE SYNONYM | 68 | DROP PROCEDURE |
31 | DROP SYNONYM | 69 | (not used) |
32 | ALTER SYSTEM SWITCH LOG | 70 | ALTER RESOURCE COST |
33 | SET TRANSACTION | 71 | CREATE SNAPSHOT LOG |
34 | PL/SQL EXECUTE | 72 | ALTER SNAPSHOT LOG |
35 | LOCK TABLE | 73 | DROP SNAPSHOT LOG |
36 | (not used) | 74 | CREATE SNAPSHOT |
37 | RENAME | 75 | ALTER SNAPSHOT |
38 | COMMENT | 76 | DROP SNAPSHOT |
Table 8 — 8. SQL Codes
Using the Oracle Communications Area
In the same way the SQLCA handles standard SQL communications; the Oracle Communications Area (ORACA) handles Oracle communications. When you need more information about runtime errors and status changes than the SQLCA provides, use the ORACA. It contains an extended set of diagnostic tools. However, use of the ORACA is optional because it adds to runtime overhead.
Besides helping you to diagnose problems, the ORACA lets you monitor your program’s use of Oracle resources such as the SQL Statement Executor and the cursor cache.
In host languages that allow local as well as global declarations, your program can have more than one ORACA. For example, it might have one global ORACA and several local ones. Access to a local ORACA is limited by its scope within the program. Oracle returns information only to the «active» ORACA. The information is available only after a commit or rollback.
Declaring the ORACA
To declare the ORACA, simply include it (using an EXEC SQL INCLUDE statement) in your host-language source file as follows:
* Include the Oracle Communications Area (ORACA). EXEC SQL INCLUDE ORACA
The ORACA must be declared outside the Declare Section.
When you precompile your program, the INCLUDE ORACA statement is replaced by several program variable declarations. These declarations allow Oracle to communicate with your program.
Enabling the ORACA
To enable the ORACA, you must specify the ORACA option, either on the command line with
ORACA=YES
or inline with
EXEC ORACLE OPTION (ORACA=YES);
Then, you must choose appropriate runtime options by setting flags in the ORACA.
What’s in the ORACA?
The ORACA contains option settings, system statistics, and extended diagnostics such as
- SQL statement text (you can specify when to save the text)
- name of the file in which an error occurred
- location of the error in a file
- cursor cache errors and statistics
Figure 8 — 3
shows all the variables in the ORACA. To see the ORACA structure and variable names in a particular host language, refer to your supplement to this Guide.
Text description of the illustration image012.gif. Figure 8 — 3. ORACA Variables
Choosing Runtime Options
The ORACA includes several option flags. Setting these flags by assigning them non-zero values allows you to
- save the text of SQL statements
- enable DEBUG operations
- check cursor cache consistency (the cursor cache is a continuously updated area of memory used for cursor management)
- check heap consistency (the heap is an area of memory reserved for dynamic variables)
- gather cursor statistics
The descriptions below will help you choose the options you need.
ORACA Structure
This section describes the structure of the ORACA, its fields, and the values they can store.
ORACAID
This string field is initialized to «ORACA» to identify the Oracle Communications Area.
ORACABC
This integer field holds the length, expressed in bytes, of the ORACA data structure.
ORACCHF
If the master DEBUG flag (ORADBGF) is set, this flag lets you check the cursor cache for consistency before every cursor operation.
The Oracle runtime library does the consistency checking and might issue error messages, which are listed in Oracle7 Server Messages. They are returned to the SQLCA just like Oracle error messages.
This flag has the following settings:
0
Disable cache consistency checking (the default).
1
Enable cache consistency checking.
ORADBGF
This master flag lets you choose all the DEBUG options. It has the following settings:
0
Disable all DEBUG operations (the default).
1
Enable all DEBUG operations.
ORAHCHF
If the master DEBUG flag (ORADBGF) is set, this flag tells the Oracle runtime library to check the heap for consistency every time the precompiler dynamically allocates or frees memory. This is useful for detecting program bugs that upset memory.
This flag must be set before the CONNECT command is issued and, once set, cannot be cleared; subsequent change requests are ignored. It has the following settings:
0
Disable heap consistency checking (the default).
1
Enable heap consistency checking.
ORASTXTF
This flag lets you specify when the text of the current SQL statement is saved. It has the following settings:
0
Never save the SQL statement text (the default).
1
Save the SQL statement text on SQLERROR only.
2
Save the SQL statement text on SQLERROR or SQLWARNING.
3
Always save the SQL statement text.
The SQL statement text is saved in the ORACA subrecord named ORASTXT.
Diagnostics
The ORACA provides an enhanced set of diagnostics; the following variables help you to locate errors quickly.
ORASTXT
This subrecord helps you find faulty SQL statements. It lets you save the text of the last SQL statement parsed by Oracle. It contains the following two fields:
ORASTXTL
This integer field holds the length of the current SQL statement.
ORASTXTC
This string field holds the text of the current SQL statement. At most, the first 70 characters of text are saved.
Statements parsed by the precompiler, such as CONNECT, FETCH, and COMMIT, are not saved in the ORACA.
ORASFNM
This subrecord identifies the file containing the current SQL statement and so helps you find errors when multiple files are precompiled for one application. It contains the following two fields:
ORASFNML
This integer field holds the length of the filename stored in ORASFNMC.
ORASFNMC
This string field holds the filename. At most, the first 70 characters are stored.
ORASLNR
This integer field identifies the line at (or near) which the current SQL statement can be found.
Cursor Cache Statistics
The variables below let you gather cursor cache statistics. They are automatically set by every COMMIt or ROLLBACK statement your program issues. Internally, there is a set of these variables for each CONNECTed database. The current values in the ORACA pertain to the database against which the last commit or rollback was executed.
ORAHOC
This integer field records the highest value to which MAXOPENCURSORS was set during program execution.
ORAMOC
This integer field records the maximum number of open Oracle cursors required by your program. This number can be higher than ORAHOC if MAXOPENCURSORS was set too low, which forced the precompiler to extend the cursor cache.
ORACOC
This integer field records the current number of open Oracle cursors required by your program.
ORANOR
This integer field records the number of cursor cache reassignments required by your program. This number shows the degree of «thrashing» in the cursor cache and should be kept as low as possible.
ORANPR
This integer field records the number of SQL statement parses required by your program.
ORANEX
This integer field records the number of SQL statement executions required by your program. The ratio of this number to the ORANPR number should be kept as high as possible. In other words, avoid unnecessary reparsing. For help, see Appendix C.
An Example
The following program prompts for a department number, inserts the name and salary of each employee in that department into one of two tables, then displays diagnostic information from the ORACA:
EXEC SQL BEGIN DECLARE SECTION; username CHARACTER(20); password CHARACTER(20); emp_name INTEGER; dept_number INTEGER; salary REAL; EXEC SQL END DECLARE SECTION; EXEC SQL INCLUDE SQLCA; EXEC SQL INCLUDE ORACA; display 'Username? '; read username; display 'Password? '; read password; EXEC SQL WHENEVER SQLERROR DO sql_error; EXEC SQL CONNECT :username IDENTIFIED BY :password; display 'Connected to Oracle'; EXEC ORACLE OPTION (ORACA=YES); -- set flags in the ORACA set oraca.oradbgf = 1; -- enable debug operations set oraca.oracchf = 1; -- enable cursor cache consistency check set oraca.orastxtf = 3; -- always save the SQL statement display 'Department number? '; read dept_number; EXEC SQL DECLARE emp_cursor CURSOR FOR SELECT ENAME, SAL + NVL(COMM,0) FROM EMP WHERE DEPTNO = :dept_number; EXEC SQL OPEN emp_cursor; EXEC SQL WHENEVER NOT FOUND DO no_more; rLOOP EXEC SQL FETCH emp_cursor INTO :emp_name, :salary; IF salary < 2500 THEN EXEC SQL INSERT INTO PAY1 VALUES (:emp_name, :salary); ELSE EXEC SQL INSERT INTO PAY2 VALUES (:emp_name, :salary); ENDIF; ENDLOOP; ROUTINE no_more BEGIN EXEC SQL CLOSE emp_cursor; EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL COMMIT WORK RELEASE; display 'Last SQL statement: ', oraca.orastxt.orastxtc; display '... at or near line number: ', oraca.oraslnr; display display ' Cursor Cache Statistics'; display '-------------------------------------------'; display 'Maximum value of MAXOPENCURSORS ', oraca.orahoc; display 'Maximum open cursors required: ', oraca.oramoc; display 'Current number of open cursors: ', oraca.oracoc; display 'Number of cache reassignments: ', oraca.oranor; display 'Number of SQL statement parses: ', oraca.oranpr; display 'Number of SQL statement executions: ', oraca.oranex; exit program; END no_more; ROUTINE sql_error BEGIN EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL ROLLBACK WORK RELEASE; display 'Last SQL statement: ', oraca.orastxt.orastxtc; display '... at or near line number: ', oraca.oraslnr; display display ' Cursor Cache Statistics'; display '-------------------------------------------'; display 'Maximum value of MAXOPENCURSORS ', oraca.orahoc; display 'Maximum open cursors required: ', oraca.oramoc; display 'Current number of open cursors: ', oraca.oracoc; display 'Number of cache reassignments: ', oraca.oranor; display 'Number of SQL statement parses: ', oraca.oranpr; display 'Number of SQL statement executions: ', oraca.oranex; exit program with an error; END sql_error;
Ошибки Оракла ORA-00000 — ORA-00999
|
Группы первой тысячи ошибок Oracle (по диапазонам кодов от 0 до 999):
- Сообщения об ошибках ORA-00000 — ORA-00099
- Ошибки областей и сегментов ORA-00100 — ORA-00299
- Ошибки I/O-управления базой данных ORA-00300 — ORA-00399
- Ошибки инициализации базы данных ORA-00400 — ORA-00499
- Сообщения об ошибках ORA-00500 — ORA-00599
- Ошибки аварийного восстановления ORA-00600 — ORA-00699
- Словарные ошибки ORA-00700 — ORA-00799
- Общие ошибки ORACLE ORA-00800 — ORA-00899
- Синтаксические ошибки ORA-00900 — ORA-00999
Сообщения об ошибках ORA-00000 — ORA-00099
Сообщения ORA-00000 — нормальное, успешное завершение, т.е., не ошибка.
Методологические ошибки доступа к ядру 0001-0049
- ORA-00001: Дублированный ключ в индексе
- ORA-00017: Превышено максимальное число вызовов
- ORA-00018: Превышено максимальное количество сеансов
- ORA-00019: Число сеансов превысило число лицензий
- ORA-00020: Превышено максимальное число(количество) процессов (num)
- ORA-00021: Сеанс занят другим процессом. Не переключайте сеанс
- ORA-00022: Неверный ID сеанса. Доступ запрещен
- ORA-00023: Сеанс содержит ссылки на частную память. Нельзя отсоеденить сеанс
- ORA-00024: Соединение более чем с одним процессом запрещено в однопользовательском режиме
- ORA-00025: Невозможно разместить [значение]
- ORA-00026: Пропущен или некорректный ID сеанса
- ORA-00027: Невозможно уничтожить текущий сеанс
- ORA-00028: Ваша сессия была уничтожена
- ORA-00029: Сеанс не пользовательский сеанс
- ORA-00030: Сеанса пользователя с указанным ID не сществует
- ORA-00031: Сеанс помечен для уничтожения
- ORA-00032: Неверный пароль перемещения сессии
- ORA-00033: Текущий сеанс с пустым паролем перемещения
- ORA-00034: Невозможно выполнить COMMIT или ROLLBACK в текущем PL/SQL сеансе
- ORA-00035: Значение LICENSE_MAX_USERS не может быть меньше чем текущее количество пользователей
- ORA-00036: Достигнуто максимальное количество уровней (значение) рекурсии SQL
- ORA-00037: Невозможно переключится на сеанс другой серверной группы
- ORA-00038: Невозможно создать сеанс. Серверная группа принадлежит другому пользователю
ENQ ошибки 0050-0080
- ORA-00050: Ошибка операционной системы при получении очереди
- ORA-00051: Истекло время ожидания ресурса
- ORA-00052: Превышено максимальное число возвращаемых ресурсов
- ORA-00053: превышено максимальное количество очередей
- ORA-00054: Ресурс занят, при обращении с указателем NOWAIT
- ORA-00055: Превышено максимальное количество DML блокировок
- ORA-00056: На заблокированный объект накладывыется DDL блокировка
- ORA-00057: Превышено максимальное количество временных блокировок таблицы
- ORA-00058: DB_BLOCK_SIZE должен быть равным с монтируемой БД
- ORA-00059: Превышено значение параметра DB_FILES
- ORA-00060: Возникла мертвая блокировка во время ожидания ресурса
- ORA-00061: Другой экземпляр имеет другие настройки DML_LOCK
- ORA-00062: DML блокировка всей таблицы ен может быть установлена. Параметр DML_LOCKS нулевой
- ORA-00063: Превышено значение параметра LOG_FILES
- ORA-00064: Размещение объекта невозможно, он слишком большой для данной операционной системы
- ORA-00065: Ошибка инициализации параметра FIXED_DATE
- ORA-00066: Значение LOG_FILES не совпадают
- ORA-00067: Некорректное значение для строкового параметра, должна быть строка
- ORA-00068: Некорректное значение для строкового параметра, должно быть строковым
- ORA-00069: Нельзя заблокировать таблицу — блокировка запрещена для [значение]
- ORA-00070: Команда [значение] некорректна
- ORA-00071: количество процессов должно быть от 1:
- ORA-00072: Указанный процесс не является активным
- ORA-00073: Указано неверное количетсво аргументов для команды
- ORA-00074: Пооцесс не определен
- ORA-00075: Процесс [значение] не найден в текущем экземпляре
- ORA-00076: dump [значение] не найден
- ORA-00077: Указанный dump некорректный
- ORA-00078: Невозможно определить dump по имени
- ORA-00079: Переменная [значение] не найдена
- ORA-00080: Была попытка сделать dump неверной области памяти
- ORA-00081: Указанный диапазон не является корректным
- ORA-00082: Диапазон памяти не в указанном диапазоне
- ORA-00083: Возможно повреждена SGA
- ORA-00084: Global Area должна быть PGA, SGA или UGA
- ORA-00085: Текущий вызов не существует
- ORA-00086: Пользовательский вызов не существует
- ORA-00087: Команда не может быть выполнена на удаленном экземпляре
- ORA-00088: Команда не может быть выполнена распеределенным сервером
- ORA-00089: Неверный номер экземпляра в команде ORADEBUG
- ORA-00090: Команда ORADEBUG не смогла корректно выделить память в кластерной БД
- ORA-00091: LARGE_POOL_SIZE должен быть указан
- ORA-00092: LARGE_POOL_SIZE должен быть больше LARGE_POOL_MIN_ALLOC
- ORA-00093: %s указан неверно
- ORA-00094: %s должен содержать значение Integer
- ORA-00096: Неверное значение [значение] для параметра [значение], должно быть из допустимого диапазона
- ORA-00097: Особенности Oracle SQL не поддерживаются SQL92:
- ORA-00099: Истекло время ожидания ресурса. Потенциальная PDML мертвая блокировка
Ошибки областей и сегментов ORA-00100 — ORA-00299
- ORA-00100: Данных не найдено
- ORA-00101: Неверная спецификация системного параметра DISPATCHERS
- ORA-00102: Указанный сетевой протокол не может быть использован диспетчерами
- ORA-00103: Неверный сетевой протокол, зарезервирован для использования диспетчерами
- ORA-00104: Обнаружена мертвая блокировка, все доступные сервера блокированы, ожидание ресурса
- ORA-00105: слишком много конфигураций диспетчера
- ORA-00106: База данных не может быть простартована или остановлена пока есть соединение с диспетчером
- ORA-00107: невозможно установить соединение с процессом прослушивателем ORACLE
- ORA-00108: Невозможна настройка диспетчера для принятия асинхронных соединений
- ORA-00111: Неверный аттрибут [значение]
- ORA-00112: Значение аттрибута пусто (null)
- ORA-00113: Наименование протокола [значение] слишком длинное
- ORA-00114: Неверное значение для системного параметра SERVICE_NAMES
- ORA-00115: Соединение сброшено, таблица соединений заполнена
- ORA-00116: Значение SERVICE_NAMES некорректно
- ORA-00117: PROTOCOL, ADDRESS или DESCRIPTION должны быть указаны
- ORA-00118: Только одно значение PROTOCOL, ADDRESS или DESCRIPTION может быть указано
- ORA-00119: Неверное значение системного параметра
- ORA-00120: Диспетчер не разрешен или не установлен
- ORA-00121: SHARED_SERVERS определен без параметра DISPATCHERS
- ORA-00122: Невозможно проинициализорвать конфигурацию сети
- ORA-00123: Простой общего сервера
- ORA-00124: DISPATCHERS указан без MAX_SHARED_SERVERS
- ORA-00125: Соединение сброшено; неверное представление
- ORA-00126: Соединение сброшено; противоречие
- ORA-00127: Диспетчер не существет
- ORA-00128: Для команды требуется имя диспетчера
- ORA-00129: Неверный адрес прослушивания
- ORA-00130: Неверный адрес для прослушивания
- ORA-00131: Сетевой протокол не поддерживает указанную регистрацию
- ORA-00132: Синтаксическая ошибка или недопустимое сетевое имя
- ORA-00150: Дублирующийся идентификатор транзакции
- ORA-00151: Дублирующийся идентификатор транзакции
- ORA-00152: Текущая сессия не соотвествует запрошенной
- ORA-00153: Ошибка в библиотеке XA
- ORA-00154: Ошибка протокола в мониторе транзакций
- ORA-00155: Не могу выполнить задание за пределами глобальной транзакции
- ORA-00160: Имя глобальной транзакции превышает масксимальную длину
- ORA-00161: Длина транзакции некорректна
- ORA-00162: Внешний идентификатор базы данных превышает маскимальное значение
- ORA-00163: Внешнее имя базы данных превышает максимальное значение
- ORA-00164: Распределенные автономные транзакции не разрешены поверх переносимых распределенных транзакций
- ORA-00165: Автономные переносимые распределенные транзакции с удаленными операциями не разрешены
- ORA-00200: Управляющий файл не может быть создан
- ORA-00201: Версия управляющенго файла [значение] несовместима с версией ORACLE [значение]
- ORA-00202: Управляющий файл: [значение]
- ORA-00203: Использование неверного управляющего файла
- ORA-00204: Ошибка чтения блока данных (блок [значение], блоков [значение]) в управляющем файле
- ORA-00205: Ошибка идентификации управляющего файла. Смотрите лог для дополнительной информации
- ORA-00206: Ошибка записи в управляющий файл (блок [значение], блоков [значение])
- ORA-00207: Управляющий файл не от этой базы данных
- ORA-00208: Количество управляющих файлов превышает допустимое значение [значение]
- ORA-00209: Блок данных управляющего файла не совпадает. Смотрите лог для получения дополнительной информации
- ORA-00210: Невозможно открыть указанный управляющий файл
- ORA-00211: Управляющий файл не совпадает с предыдущим
- ORA-00212: Размер блока [значение] меньше минимально требуемого [значение]
- ORA-00213: Невозможно повторно использовать управляющий файл, размер файла %1: требуется %2:
- ORA-00214: Версия управляющего файла несовместима с версией файла
- ORA-00215: Должен быть минимум один управляющий файл
- ORA-00216: Размер управляющего файла не может быть изменен для переноса с 8.0.2:
- ORA-00217: Размер управляющего файла не может быть изменен для переноса с 9.0.1:
- ORA-00218: Размер блока данных управляющих файлов не совпадает с размером указанным в параметре DB_BLOCK_SIZE
- ORA-00219: Размер управляющего файла превышает установленный размер
- ORA-00220: Управляющий файл не может быть подключен, смотрите alert-log для более детальной информации
- ORA-00221: Ошибка записи в управляющий файл
- ORA-00222: Операция пытается использовать имя уже примонтированного управляющего файла
- ORA-00223: Конвертируемый файл неверный или имеет неверную версию
- ORA-00224: Неудачное изменение размера управляющего файла с неверным типом записи
- ORA-00225: Ожидаемый размер управляющего файла [значение] отличается от актуального [значение]
- ORA-00226: Операция невозможна пока альтернативный управляющий файл открыт
- ORA-00227: В управляющем файле найден поврежденный блок данных (блок [значение] блоков [значение]).
- ORA-00228: Длина имени альтернативного контрольного файла превышает допустимое значение [значение]
- ORA-00229: Операция запрещена. Файл-снимок (snapshot) уже помещен в очередь и занят процессом
- ORA-00230: Операция запрещена. Очередь снимоков контрольного файла недоступна
- ORA-00231: Снимок управляющего файла не назван
- ORA-00232: Снимок управляющего файла не существует, поврежден или нечитаемый
- ORA-00233: Копия управляющего файла повреждена или нечитаема
- ORA-00234: Ошибка идентификации или открытия снимка или копирования управляющего файла
- ORA-00235: Управляющий файл заблокирован для паралельного изменения
- ORA-00236: Снимок отменен, выбран резервный управляющий файл
- ORA-00237: Операция создания снимка запрещена. Создан новый управляющий файл
- ORA-00238: Операция пытается использовать имя файла как и имя базы данных
- ORA-00250: Архиватор не запущен
- ORA-00251: LOG_ARCHIVE_DUPLEX_DEST не может быть той же самой директорией что и %1:
- ORA-00252: Журнал пуст. Архивирование невозможно
- ORA-00253: Длина указанной строки превышает предел
- ORA-00254: Ошибка в управляющей строке архива
- ORA-00255: Ошибка во время архивации log-файла
- ORA-00256: Произошла ошибка при разборе архивной строки
- ORA-00257: Ошибка архиватора. Не могу подсоеденится пока занят ресурс
- ORA-00258: При ручном архивировании в режиме NOARCHIVELOG log должен быть указн
- ORA-00259: Журнал открытого экземпляра является текущим журнало и не может быть заархивирован
- ORA-00260: Не могу найти активный журнал очереди [значение] для потока [значение]
- ORA-00261: Журнал был изменен или архивирован
- ORA-00262: Текущий журнал [значение] занят другим потоком [значение], невозможно переклюится
- ORA-00263: Нет журналов для архивирования для потока [значение]
- ORA-00264: Восстаовления не требуется
- ORA-00265: Требуется восстановление экземпляра, новозможно утсановить режим ARCHIVELOG
- ORA-00266: Требуется имя архивного журнала
- ORA-00267: Имя архивного журнала не требуется
- ORA-00268: Указанный журнальный файл не существует
- ORA-00269: Указанный журнальный файл — часть потока [значение] не [значение]
- ORA-00270: Ошибка создания архивного журнала [значение]
- ORA-00271: Нет журналов требующих архивации
- ORA-00272: Ошибка записи в архивный журнал [значение]
- ORA-00273: Восстановление данных загруженных напрямую без журнализации
- ORA-00274: Указано неверное значение [значение] параметра восстановления
- ORA-00275: Процедура восстановления уже запущена
- ORA-00276: Ключевое слово CHANGE указано, но не указан номер изменения
- ORA-00277: Недопустимая опция восстановления UNTIL флаг [значение]
- ORA-00278: Журнальный файл [значение] больше не требуется для восстановления
- ORA-00279: Требуется имя журнального файла
- ORA-00280: Требуется имя потока и последовательности
- ORA-00281: Восстановление не может быть выполнено с использованием диспетчера
- ORA-00282: UPI вызов не поддерживается, используйте ALTER DATABASE RECOVER
- ORA-00283: Сеанс восстановления отменен из за ошибок
- ORA-00284: Сеанс восстановления в процессе
- ORA-00285: Значение TIME задано неверно
- ORA-00286: Нет доступных файлов или файлов с корректными данными
- ORA-00287: Указанный номер изменения [значение] не найден в потоке [значение]
- ORA-00288: Для продолжения восстановления используйте ALTER DATABASE RECOVER CONTINUE
- ORA-00289: Переменная [значение]
- ORA-00290: Ошибка операционной системы. См сообщение об ошибке ниже
- ORA-00291: Для PARALLEL требуется числовое значение
- ORA-00292: Компонет «паралельное восстановление» не установлен
- ORA-00293: Управляющий файл не синхронизирован с журналом повторного выполнения
- ORA-00294: Указан неверный формат для архивного журнала [значение]
- ORA-00295: Неверный номер файла данных/временных данных [значение], должно быть от 1: до [значение]
- ORA-00296: Превышено значение RECOVER DATAFILE LIST
- ORA-00297: Требуется указать RECOVER DATAFILE LIST перед RECOVER DATAFILE START
- ORA-00298: Пропущенное или неверное значение аттрибута
- ORA-00299: Восстановление на файловом уровне файла данных %1
Ошибки I/O-управления базой данных ORA-00300 — ORA-00399
Ошибки управления входом в БД Оракл и выходом из неё:
- ORA-00300: Недопустимый размер блока журнала повторного выполнения, указанный размер [значение] превышает предел размер [значение]
- ORA-00301: Ошибка в добавлении файла протокола [значение] — файл не может быть создан
- ORA-00302: Превышен лимит количества журнальных файлов
- ORA-00303: невозможно выполнить Parallel Redo
- ORA-00304: Запрашиваемый INSTANCE_NUMBER занят
- ORA-00305: Журнал [значение] потока [значение] не согласован и принадлежит другой базе данных
- ORA-00306: Достигнут предел количества экземпляров [значение]
- ORA-00307: Запрошенный INSTANCE_NUMBER выходит за допустимые пределы, максимум [значение]
- ORA-00308: Невозможно открыть архивный журнал [значение]
- ORA-00309: Журнал принадлежит другой базе данных
- ORA-00310: Архивный журнал содержит последовательность [значение]; требуется последовательность [значение]
- ORA-00311: Невозможно прочитать заголовок архивного журнала
- ORA-00312: Доступный журнал [значение] поток [значение]
- ORA-00313: Ошибка при открытии файла журнальной группы [значение] поток [значение]
- ORA-00314: Журнал [значение], ожидаемая последовательность [значение] не совпадает с [значение]
- ORA-00315: Журнал [значение] поток [значение], неверное значение [значение] в заголовке
- ORA-00316: Журнал [значение], значение [значение] в заголовке указывает что это не журнальный файл
- ORA-00317: Указанный файл [значение] не является журнальным файлом
- ORA-00318: Журнал [значение] превысил допустимый размер [значение] не совпадает с [значение]
- ORA-00319: Журнал [значение] имеет некорректный статус сброса
- ORA-00320: Невозможно прочитать заголовок файла [значение] потока [значение]
- ORA-00321: Невозможно обновить данные в заголовке журнального файла [значение] поток [значение]
- ORA-00322: Журнал [значение] потока [значение] не текуща копия
- ORA-00323: Текущий журнал потока [значение] не пригоден к использованию и все другие требуют архивации
- ORA-00324: Имя журнального файла [значение] переведенное [значение] слишком длинное, превышен допустимый предел [значение]
- ORA-00325: Архивный журнал потока [значение] содержит неверное значение [значение] в заголовке
- ORA-00326: Журнал начинается на [значение], требуется ранее измененное [значение]
- ORA-00327: Журнал [значение] потока [значение] имеет физический размер [значение] меньшее чем требуется [значение]
- ORA-00328: Архивный журнал заканчивается на [значение], требуется более позднее изменение [значение]
- ORA-00329: Архивный журнал начинается на [значение], требуется изменение [значение]
- ORA-00330: Архивный журнал заканчивается на [значение], требуется изменение [значение]
- ORA-00331: Версия журнала [значение] не совместима с версией ORACLE [значение]
- ORA-00332: Архивный журнал очень маленький, возможно неполностью заархивирован
- ORA-00333: Журнал повторного выполения прочитал [значение] ошибочных блоков из доступных [значение]
- ORA-00334: Архивный журнал [значение]
- ORA-00335: Доступный журнал [значение]: Нет журнала с таким номером, журнал не существует
- ORA-00336: Размер блока файла журнала меньше чем минимальный блок [значение]
- ORA-00337: Журнальный файл [значение] не существует и размер не указан
- ORA-00338: Журнал [значение] больше чем последнее значение управляющего файла
- ORA-00339: Архивный журнал не содержит каких либо повторных исполнений
- ORA-00340: I/O ошибка при обработке журнала [значение] потока [значение]
- ORA-00341: Журнальный файл [значение] имеет неверный номер [значение] в заголовке
- ORA-00342: Архивный журнал не содержит информации SCN [значение]
- ORA-00343: Слишком много ошибок, журнал закрыт
- ORA-00344: Невозможно пересздать доступный журнал [значение]
- ORA-00345: Ошибка записи в журнал повторного исполнения, блок [значение] всего [значение]
- ORA-00346: Журнал отмечен как устаревший (STALE)
- ORA-00347: Журнал [значение] потока [значение] имеет размер блока [значение], не совпадает, должно быть [значение]
- ORA-00348: Неудачная обработка повторного восстановления, экземпляр должен быть остановлен
- ORA-00349: Отказ в получении размера блока для [значение]
- ORA-00350: Журнал [значение] (поток [значение])экземпляра [значение] требует архивирования
- ORA-00351: Неправильное время для восстановления
- ORA-00352: Все журналы из потока [значение] должны быть архивированы — нельзя разрешить
- ORA-00353: Поврежден журнал блок [значение] изменение [значение] время [значение]
- ORA-00354: Поврежден заголовок блока журнала повторного выполнения
- ORA-00355: Номер изменения за пределами последовательности
- ORA-00356: Неверная длина описания изменения
- ORA-00357: Слишком много членов указано для журнального файла, максимум [значение]
- ORA-00358: Слишком много членов указано, максимум [значение]
- ORA-00359: Группа журнальных файлов [значение] не существует
- ORA-00360: Не член журнального файла: [значение]
- ORA-00361: Невозможно удалить последний журнал [значение] из группы [значение]
- ORA-00362: Требуемый член является верным журнальным файлом в группе [значение]
- ORA-00363: Журнал не архивированный
- ORA-00364: Невозможно писать в заголовок нового журнала
- ORA-00365: Указанный журнал не корректный
- ORA-00366: Журнал [значение] потока [значение], ошибка контрольной суммы в заголовке файла
- ORA-00367: Ошибка контрольной суммы в заголовке файла
- ORA-00368: Ошибка контрольной суммы в блоке журнала повторного выполнения
- ORA-00369: Текущий журнал потока [значение] испорчен и другой журнал очищен
- ORA-00371: Недостаточно памяти в разделяемом пуле, должно быть не меньше [значение]
- ORA-00372: Файл [значение] не может быть изменен в настоящее время
- ORA-00373: Версия открытого журнала [значение] несовместима с версией ORACLE [значение]
- ORA-00374: Значение параметра db_block_size=[значение] некорректно; должен быть составной в диапазоне [значение..значение]
- ORA-00375: Невозможно получить значение по-умолчанию db_block_size
- ORA-00376: Файл [значение] не может быть прочитан в настоящее время
- ORA-00377: Частое резервное копирование файла [значение] причина тупика в операциях записи
- ORA-00378: Буферный кэш не может быть создан как указано
- ORA-00379: Нет свободных буферов в буферном кэше [значение] для блока [значение]K
- ORA-00380: Не могу указать db_[значение]k_cache_size [значение]K это стандартный размер блока.
- ORA-00381: Невозможно использовать старый и новый параметры для указания размера буферного кэша
- ORA-00382: %s неверный размер блока, верное значение [значение..значение]
- ORA-00383: Значение по умолчанию для кэша не может быть уменьшено до нуля
- ORA-00384: Недостаточно памяти для увеличения кэша
- ORA-00390: Журнал [значение] потока [значение] очищен и не может быть текущим журналом
- ORA-00391: Все потоки с этого момента должны переключится на новый формат журнала
- ORA-00392: Журнал [значение] потока [значение] был очищен, операция не разрешена
- ORA-00393: Журнал [значение] потока [значение] необходим для восстановления недоступной (offline) базы данных.
- ORA-00394: Доступный журнал заново используется во время его архивирования
- ORA-00395: Журнал для клона базы данных должен быть переименован
- ORA-00396: Ошибка [значение] требует отката на однопроходное восстановление
- ORA-00397: Восстановление экземпляра прервано с ошибкой
- ORA-00398: Восстановление прервано до правильной переконфигурации
- ORA-00399: Поврежденное описание изменений в журнале повторного исполнения
Ошибки инициализации базы данных ORA-00400 — ORA-00499
- ORA-00400: Неверное значение [значение] для параметра [значение]
- ORA-00401: Значение для параметра [значение] не поддерживается этой версией
- ORA-00402: Изменения базы данных версии [значение] не могут быть использованы версией [значение]
- ORA-00403: [значение] не тоже самое как в других экземплярах [значение]
- ORA-00404: Преобразованный файл не найден: [значение]
- ORA-00405: Тип совместимости [значение]
- ORA-00406: Параметр COMPATIBLE требует значение [значение] или выше
- ORA-00407: Откат обновления с версии [значение].[значение] до версии [значение].[значение] неразрешено
- ORA-00408: Значение параметра [значение] выставлено в TRUE
- ORA-00436: Oracle не лицензирован. Обратитесь в корпорацию Oracle для помощи
- ORA-00437: Дополнительные возможности Oracle не лицнзированны. Обратитесь в корпорацию Oracle для помощи
- ORA-00438: Опция [значение] не установлена
- ORA-00439: Дополнительная возможность не разрешена: [значение]
- ORA-00443: Фоновый процесс [значение] не запущен
- ORA-00444: Фоновый процесс [значение] вышел из строя при запуске
- ORA-00445: Фоновый процесс [значение] не стартовал по истечение [значение] секунд
- ORA-00446: Фоновый процесс стартовал, когда этого не ожидали
- ORA-00447: Критическая ошибка в фоновом процессе
- ORA-00448: Нормальное завершение фонового процесса
- ORA-00449: Фоновый процесс [значение] внезапно прервал работу с ошибкой [значение]
- ORA-00470: LGWR процесс завершился с ошибкой
- ORA-00471: DBWR процесс завершился с ошибкой
- ORA-00472: PMON процесс завершился с ошибкой
- ORA-00473: ARCH процесс завершился с ошибкой
- ORA-00474: SMON процесс завершился с ошибкой
- ORA-00475: TRWR процесс завершился с ошибкой
- ORA-00476: RECO процесс завершился с ошибкой
- ORA-00477: SNP* процесс завершился с ошибкой
- ORA-00478: SMON процесс завершился с ошибкой [значение]
- ORA-00480: LCK* процесс завершился с ошибкой
- ORA-00481: LMON процесс завершился с ошибкой
- ORA-00482: LMD* процесс завершился с ошибкой
- ORA-00483: Во время остановки процесс завершился ненормально
- ORA-00484: LMS* процесс завершился с ошибкой
- ORA-00485: DIAG процесс завершился с ошибкой [значение]
Сообщения об ошибках ORA-00500 — ORA-00599
- ORA-00568: Максимальное количество прерываний обработчика превышено
Ошибки аварийного восстановления ORA-00600 — ORA-00699
- ORA-00600: Код внутренней ошибки,
аргументы [значение], [значение], [значение], [значение], [значение], [значение], [значение], [значение] - ORA-00601: Конфликт чистых блокировок
- ORA-00602: Внутренее программное исключение
- ORA-00603: Сеанс сервера Oracle был прерван критичной ошибкой
- ORA-00604: Ошибка случилась на рекурсивном уровне SQL [значение]
- ORA-00606: Внутренний код ошибки
- ORA-00607: Внутреняя ошибка при изменении блока данных
Словарные ошибки ORA-00700 — ORA-00799
- ORA-00701: Объект необходимый для старта базы данных не может быть изменен
- ORA-00702: Загрузчик версии [значение] несовместим с версией [значение]
- ORA-00703: Максимальное количество блокировок кэша строк экземпляра превышено
- ORA-00704: Процесс загрузки завершился аварийно
- ORA-00705: Неверное состояние во время запуска; остановите экземпляр и заново запустите
- ORA-00706: Ошибка смены формата файла [значение]
Общие ошибки ORACLE ORA-00800 — ORA-00899
-
ORA-0800: buffer write process is not active (процесс записи в буфер не активен).
Причина: Проблема связана с попыткой запуска
ORACLE, что вызвало снятие процесса записи в буфер.
Обычно это сообщение выдается вместе с сообщением
о системной ошибке, обьясняющей причину сбоя.
Действие: Используйте сообщение о системной ошибке
( если такое есть ) для выяснения причины ошибки.
Если системная ошибка отсутствует, обратитесь к
руководству по инстолляции ORACLE за перечнем требо-
ваний. Убедитесь, что все логические имена ORACLE
присвоены верно, что достаточно свободного дискового
пространства в директории ORACLE, и что достаточное
число глобальных секций и страниц. Также убедитесь в
наличии у бюджета ORACLE трубуемого приоритета. Если
источник проблемы не определен, обратитесь к соответ-
ствущему установочному обеспечению. -
ORA-0801: after image write process is not active (процесс записи последущего вида не активен).
Причина: Это свойство не поддерживается.
Действие: Обратитесь к соответствующему установочному обеспечению. -
ORA-0802: invalid context area (недопустимая контекстная область).
Причина:Это сообщение о внутренней ошибке, которая не может произойти при нормальной работе.
Действие: Обратитесь к соответствуюшему наладочному обеспечению с подробным описанием проблемы. -
ORA-0805: opiodr: inconsistent recursion level number (несовместимый уровень рекурсии).
Причина:Это сообщение о внутренней ошибке, которая не может произойти при нормальной работе.
Действие: Обратитесь к соответствуюшему наладочному обеспечению с подробным описанием проблемы. -
ORA-0806: before image process is not active (процедура предварительного вида не активна).
Причина: Проблема связана с попыткой запуска
ORACLE, что вызвало снятие процесса предварительного
вида.Обычно это сообщение выдается вместе с сообще-
нием о системной ошибке, обьясняющей причину сбоя.
Действие: Используйте сообщение о системной ошибке
(если такое есть) для выяснения причины ошибки.
Если системная ошибка отсутствует, обратитесь к
руководству по инстолляции ORACLE для вашей опера-
ционной системы,чтобы проверить правильность инстол-
ляции. Если источник проблемы не определен, обрати-
тесь к соответствущему установочному обеспечению. -
ORA-0807: clean up process is not active (процедура очистки не активна).
Причина: Проблема связана с попыткой запуска
ORACLE, что вызвало снятие процесса предварительного
вида.Обычно это сообщение выдается вместе с сообще-
нием о системной ошибке, обьясняющей причину сбоя.
Действие: Используйте сообщение о системной ошибке
( если такое есть ) для выяснения причины ошибки.
Если системная ошибка отсутствует, обратитесь к
руководству по инстолляции ORACLE для вашей опера-
ционной системы,чтобы проверить правильность инстол-
ляции. Если источник проблемы не определен, обрати-
тесь к соответствущему установочному обеспечению. -
ORA-0809: opispf: invalid special function code (неверный спецкод функции).
Причина:Это сообщение о внутренней ошибке, которая не может произойти при нормальной работе.
Действие: Обратитесь к соответствуюшему наладочному обеспечению с подробным описанием проблемы. -
ORA-0810: opiomc: context area not remapped at original addres (контекстная область не соответствует начальному адресу).
Причина:Это сообщение о внутренней ошибке, которая не может произойти при нормальной работе.
Действие: Обратитесь к соответствуюшему наладочному обеспечению с подробным описанием проблемы. -
ORA-0811: readahead process is not active (процедура чтения вперед не активна).
Причина: Проблема связана с попыткой запуска
ORACLE, что вызвало снятие процесса чтения вперед.
Обычно это сообщение выдается вместе с сообщением
о системной ошибке, обьясняющей причину сбоя.
Действие: Используйте сообщение о системной ошибке
( если такое есть ) для выяснения причины ошибки.
Если системная ошибка отсутствует, обратитесь к
руководству по инстолляции ORACLE для вашей опера-
ционной системы,чтобы проверить правильность инстол-
ляции. Если источник проблемы не определен, обрати-
тесь к соответствущему установочному обеспечению. -
ORA-0813: assertion failure (добавление снято).
Причина:Это сообщение о внутренней ошибке, относящейся к ORACLE SORT.
Это не может произойти при нормальной работе.
Действие: Обратитесь к соответствуюшему наладочному обеспечению с подробным описанием проблемы. -
ORA-0814: ltbdrv: illegal lock mode (недопустимый режим защиты).
Причина:Это сообщение о внутренней ошибке, которая не может произойти при нормальной работе.
Действие: Обратитесь к соответствуюшему наладочному обеспечению с подробным описанием проблемы. - ORA-00816: error message translation failed
(не достает перевода сообщения об ошибке / сбой трансляции сообщения об ошибке).
Причина:Это сообщение о внутренней ошибке, которая не может произойти при нормальной работе.
Действие: Обратитесь к соответствуюшему наладочному обеспечению с подробным описанием проблемы. -
ORA-0817: prsgkw: internal error token not found (индентификатор внутренней ошибки не обнаружен).
Причина:Это сообщение о внутренней ошибке, которая не может произойти при нормальной работе.
Действие: Обратитесь к соответствуюшему наладочному обеспечению с подробным описанием проблемы. -
ORA-0818: opispf: osf too big (osf слишком велик).
Причина:Это сообщение о внутренней ошибке, которая не может произойти при нормальной работе.
Действие: Обратитесь к соответствуюшему наладочному обеспечению с подробным описанием проблемы.
Синтаксические ошибки ORA-00900 — ORA-00999
-
ORA-00900: Неверное SQL предложение.
Причина: Введенный вами оператор не опознан как допустимая команда SQL.
Действие:
Проверьте опечатки,убедитесь, что ключевые слова команд SQL начинаются одним из следущих слов:
ALTER, AUDIT, CREATE, DELETE, DROP, GRANT, INSERT, NOAUDIT, RENAME, REVOKE, SELECT, UPDATE, LOCK, VALIDATE.
Другие команды вызовут эту ошибку.
Комментприй из практики:
Однажды ошибка затаилась хитро — самым первым байтом стоял плюсик перед «create or replace function …».
Но чаще первым байтом может быть «s», который ставится при сохранении (Ctrl-S), когда Ctrl слабо нажимаешь. - ORA-00901: Неверный синтаксис команды CREATE / Неверная команда на создание.
Причина: В команде CREATE использована недопустимая опция CREATE.
Действие: Проверьте опечатки, убедитесь,что за командой CREATE следует одна из следущих опций :
[UNIQUE] INDEX, PARTITION, SPACE DEFINITION, [PUBLIC] SYNONYM, TABLE или VIEW. -
ORA-00902: Неверный тип данных.
Причина: Введенный тип данных в операторе CREATE или ALTER TABLE не является допустимым.
Действие:
Проверьте опечатки, убедитесь, что за каждым именем колонки следует один из следущих типов данных:
DATA, CHAR, NUMBER, RAW, LONG или LONG RAW. -
ORA-00903: Неверное имя таблицы.
Причина:
Введенные имена таблицы или группы не существуют или недопустимые.
Это сообщение так же появляется в сучае, если неверное или несуществующее имя группы
описано в команде ALTER/DROP CLUSTER.
Действие:
Проверьте опечатки. Допустимое имя группы должно начинаться с буквы
и содержать только буквы,цифры и спецсимволы: $,# и _.
Имя должно быть не длиннее 30 символов и не являться зарезервированным словом. -
ORA-00904: Неверное имя колонки.
Причина: Введенное имя колонки отсутствует или недопустимо.
Действие: Введите верное имя колонки.
Допустимое имя должно начинаться с буквы и содержать только буквы,цифры и спецсимволы: $,# и _.
Имя должно быть не длиннее 30: символов и не являться зарезервированным словом.
Если оно содержит другие символы, оно долно быть в двойных кавычках. -
ORA-00905: Пропущено ключевое слово.
Причина: Требуемое ключевое слово пропущено.
Действие: Проверьте синтаксис команды и добавьте пропущенные ключевые слова. -
ORA-00906: Пропущена левая скобка.
Причина: Требуемая левая скобка пропущена. Основные
команды (такие как CREATE TABLE,CREATE CLUSTER и
INSERT) требуют список пунктов, заключенный в скобки.
Скобки также необходимы вокруг последовательностей в
предложении WHERE и в UPDATE таблица SET колонка = (SELECT …).
Действие: Проверьте синтаксис команды и вставь-
те пропущенные скобки. -
ORA-00907: missing right parenthesis
пропущена правая скобка
Причина: Левая скобка введена бз закрывающей правой
или предыдущая информация была заключена в скобки.
Все скобки должны быть парными.
Действие: Вставьте закрывающую правую скобку. -
ORA-00908: missing NULL keyword
пропущено ключевое слово NULL
Причина: В командах СREATE или ALTER TABLE, NOT
было введенодля указания, что никакие нулевые величи-
ны не допустимы в этой колонке,но ключевое слово
NULL было пропущено.
Действие: Если требуете наличие значения в этой
колонке, замените ключевое слово NOT на NOT NULL. - ORA-00909: invalid number of arguments
недопустимое число аргументовПричина: Указание на встроенную функцию ORACLE
было сделано с неверным числом аргументов.Все фун-
кции ORACLE, за исключением SYSDATE требуют по
крайней мере один аргумент.
Действие: Проверьте синтаксис команды и введите
введите необходимое число аргументов . - ORA-00910: specified length too large for CHAR colum
указанная длина слишком велика для колонки CHAR
Причина: Размер поля знака не указан или указан
неверно. Необходимо указывать максимальную длину
для каждой колонки знаков.Это длина может принимать
значения от 0: до 240: .
Действие: Введите максимальную длину из диапазона
от 0 до 240: . - ORA-00911: invalid character
неверный знакПричина: Спецзнак неверен или допустим только в
определенных местах. Если спецзнак( кроме $, # и _ )
используется в имени и имя не заключено в двойные
кавычки («), появится данное сообщение.
Действие: Удалите неверный знак из команды. - ORA-00912: operand pop оperation with no operands on stack
для операции с операндом рор отсутствуют операнды в стеке
Причина: Это сообщение о внутренней ошибке,
которая не может произойти при нормальной работе .
Действие: Обратитесь к соответствуюшему наладочному
обеспечению с подробным описанием проблемы. - ORA-00913: too many values
слишком много значений
Причина: Команда предполагает два одинаковых
набора значений, но во втором наборе пунктов больше,
чем в первом. Например: подзапрос в предложении
WHERE или HAVING может быть слишком много колонок,
или в предложениях VALUES или SELECT колонок больше,
чем в INSERT.
Действие: Проверьте число пунктов и измените их. - ORA-00914: missing ADD keyword
пропущено ключевое слово ADD
Причина: Команда ALTER PARTITION введна без
ключевого слова ADD.
Действие: проверьте синтаксис команды и повторите
ее. - ORA-00915: network access of dictionary table not currently allowed
неверно установлен сетевой доступ к словарной таблице
Причина:Это сообщение о внутренней ошибке,
которая не может произойти при нормальной работе .
Действие: Обратитесь к соответствуюшему наладочному
обеспечению с подробным описанием проблемы. - ORA-00917: missing comma
пропущена запятая
Причина: Пропущена запятая в списке колонок,или
в списке значений в операторе INSERT, или в списке
формы ((c,d),(e < f),…).
Действие: Проверьте сиснтаксис в вашем SQL оператор
и, если необходимо, добавьте пропущенную запятую. - ORA-00918: column ambigiuously defined
неоднозначное определение колонки
Причина: Колонка, использованая для присоединения
существует в более, чем одной таблице. При присоеди-
нении любая колонка, присутствующая более чем в одной
таблице, должна содержать имя таблицы. Имя колонки
должно указываться следущим образом: TABLE.COLUM
или TABLE_ALIAS.COLUMN, EMP.DEPTNO или E.DEPTNO, а
не просто EMP.
Действие: Введите имя таблицы в имя колонки перед
точкой или альтернативное имя таблицы, как показано
выше. - ORA-00919: invalid functio
неверная функция
Причина: Ввод, похожий на функцию, типа
функция(аргумент), не опознан как функция ORACLE.
Действие: Обратитесь к руководству за списком
допустимых имен функций. - ORA-00920: invalid relational operator
неверный оператор отношения
Причина: Задача поиска с неверным или пропущенным
оператором условия.
Действие: Введите допустимый условный оператор.
Допустимы следущие орераторы отношения:=, !=, <>, >,
>=, <, <=,IN, IS[NOT], NULL, LIKE, и BETWEEN. - ORA-00921: unexpected end of SQL command
неожиданный конец команды SQL
Причина: Команда SQL не полная. Была введена часть
верной команды, но по крайней мере одина главная ком-
понента пропущена.
Действие: Проверьте синтаксис команды и вставьте
пропущенные компоненты. - ORA-00922: invalid optio
неверная опция
Причина: Неверная опция была описана в определении
колонки или в определении области.
Действие: Удалите неверную опцию из определения
колонки или области. Допустимой опцией, описывающей
колонку, является NOT NULL для указания, что колонка
не может содержать NULL значения. Все прочее,следущее
за типом данных, кроме запятой или закрывающей скобки,
классифицируется как недопустимая опция. Описывая
длину для DATA или тип данных LONG, вы получите данное
сообщение об ошибке. В описании определения области
допустимы только следущие опции: INITIAL, INCREMENT и
MAXEXTENTS,( для DATAPAGES и INDEXPAGES) и PCTFREE
( только для DATAPAGES ). - ORA-00923: missing FROM keyword
пропущено ключевое слово FROM
Причина: В командах SELECT или REVOKE ключевое слово
FROM или пропущено, или неверно помещено, или с опе-
чаткой. Ключевое слово FROM должно следовать в команде
SELECT за выбранным пунктом, или за быбранным именем
таблицы в команде REVOKE.
Действие: Вставьте на место слово FFROM. Выбранный
список может быть сам по себе ошибочным. Убедитесь,
что использованы одинарные кавычки для выделения
альтернативного имени, и является или нет альтерна-
тивное имя зарезервированным словом. - ORA-00924: missing BY keyword
пропущено ключевое слово BY
Причина: Пропущено ключевое слово BY в выражениях
GROUP BY, ORDER BY, или CONNECTED BY. Кроме того в
команде GRANT за словом INDENTIFIED должно следовать
BY.
Действие: Правильно вставьте слово BY. - ORA-00925: missing INTO keyword
пропущено ключевое слово INTO
Причина: Была употреблена команда INSERT без ключе-
чевого слова INTO.
Действие: Замените INSERT на INSERT INTO. - ORA-00926: missing VALUES keyword
пропущено ключевое слово VALUES
Причина: Оператор INSERT без ключевого слова
VALUES или SELECT. За выражением INSERT INTO должно
следовать выражение VALUES или SELECT последователь-
ность.
Действие: Введите после выражения INSERT INTO
выражение VALUES или последовательность. - ORA-00927: missing equal sig
пропущен знак равно
Причина: Знак равно пропущен в одном из следущих
мест: * в выражении SET команды UPDATE
* после ! для указания на неравенство
* в выражении PCTFREE команды CREATE INDEX
Действие: Вставьте знак равенства. - ORA-00928: missing SELECT keyword
пропущено ключевое слово SELECT
Причина: В команду CREATE VIEW должна быть включена
SELECT последовательность.
Действие: Вставьте требуемое выражение SELECT в
команду CREATE VIEW. - ORA-00929: missing period
пропущен период
Причина:Это сообщение о внутренней ошибке,
которая не может произойти при нормальной работе .
Действие: Обратитесь к соответствуюшему наладочному
обеспечению с подробным описанием проблемы. - ORA-00930: missing asterisk
пропущена звездочка *
Причина:Это сообщение о внутренней ошибке,
которая не может произойти при нормальной работе .
Действие: Обратитесь к соответствуюшему наладочному
обеспечению с подробным описанием проблемы. - ORA-00931: missing identifier
порущен индентификатор
Причина:Это сообщение о внутренней ошибке,
которая не может произойти при нормальной работе .
Действие: Обратитесь к соответствуюшему наладочному
обеспечению с подробным описанием проблемы. - ORA-00932: inconsistent datatypes
несовместимый тип данных
Причина: Попытка добавить символьное поле к полю
данных. Данные могут быть добавлены только к числовым
полям.
Действие: Преобразуйте символьное поле в числовое
поле с помощью функции TO_NUMBER перед добавлением
поля данных. - ORA-00933: SQL comand not properly ended
команда SQL не закончена
Причина: SQL-команда закончена неверным выражением.
Например: выражение ORDER BY может быть включено в
команду CREATE VIEW или INSERT.Однако ORDER BY не
должна использоваться для создания очередного обзора
или включаться в основной порядок.
Действие: Проверьте синтаксис команды и удалите
лишние компоненты. Вы должны уметь дублировать удален-
ные выражения другими командами. Например, если вы
желаете упорядочить строки обзора, действуйте так же,
как при запросе на обзор, но не как при создании его.
Эта ошибка также может произойти при применении
SQL*Forms, если смещено продолжение строки. Проверьте
смещения и удалите пробелы. Вы должны испоьзовать
соответствующие окончания SQL, если используете I
выражение с одним аргументом, например: IN(X). В вы-
ражении IN должно испоьзоваться не менее двух аргу-
ментов. - ORA-00934: set function not allowed here
данная функция недопустима здесь
Причина: одна из групповых функций ( таких как
AVG, SUM, MAX, MIN, COUNT) была использована в вы-
жении WHERE или GROUP BY.
Действие: Удалите групповую функцию из выражений
WHERE или GROUP BY.Вы можете получить желаемый резу-
льтат,включив функцию в запрос или предложение HAVING. - ORA-00935: set function is nested too deep
данная функция является слишком вложеной
Причина:Это сообщение о внутренней ошибке,
которая не может произойти при нормальной работе .
Действие: Обратитесь к соответствуюшему наладочному
обеспечению с подробным описанием проблемы. - ORA-00936: missing expressio
пропущено выражение
Причина: Необходимая часть выражения пропущена.
Например, команда SELECT вводится без списка колонок,
или с несовместимым выражением типа (SAL+). Это может
произойти и в том случае, если пропущены зарезервиро-
ванные слова типа SELECT TABLE.
Действие: Проверьте синтаксис команды и введите
пропущенные команды. - ORA-00937: not a single group set functio
устанавливается не только групповая функция
Причина: В запрос нельзя одновременно включать и
групповую функцию ( AVG, SUM,COUNT,MIN или MAX) и
собственное выражение для колонки, пока выражение для
колонки не включено в выражение GROUP BY.
Действие: Удалите из запроса или выражение для
колонки, или групповую функцию, или добавьте выражение
GROUP BY , в которое включите перечисление колонок. - ORA-00938: not enough arguments for functio
недостаточно аргуметов для функции
Причина: В функции описано слишком мало аргументов.
Действие: Проверьте синтаксис функции и добавьте
все необходимые аргументы. - ORA-00939: too many arguments for functio
cлишком много аргументов в функции
Причина: В функции описано слишком много аргументов.
Действие: Проверьте синтаксис функции и опишите
только необходимые аргументы. - ORA-00940: invalid ARTER comand
неверная команда ALTER
Причина: Описана неверная опция ALTER. Только
разделы и таблицы могут быть неповторяющимися. Пра-
вильная команда ALTER должна начинаться одним из сле-
дущих вариантов : ALTER TABLE или ALTER PARTITION.
Действие: Проверьте синтаксис рпавильного написания
команды ALTER. - ORA-00941: missing cluster name
пропущено имя группы
Причина: Имя группы или пропущено или неверное.
Действие: Опишите верное имя группы. Допустимое имя
группы начинается с буквы, содержит не более 30: сим-
волов и состоит только из букв, цифр и спецсимволов $,
_ и #. Оно не должно быть зарезервированным словом.
Имя должно быть напечатано сразу за ключевым словом
CREATE CLUSTER. - ORA-00942: table or view does not exist
таблица или обзор не существуют
Причина: Данная таблица или обзор не существуют.
или введено имя обзора вместо таблицы. Существующие
пользовательские таблицы и обзоры можно просмотреть
в обзоре TAB.
Действие: Проверьте опечатки и не ввели ли вы имя
обзор вместо таблицы. Введите существующие имена. - ORA-00943: cluster does not exist
группа не существует
Причина: Ресурс пользователя не включен в группу
под описанным именем.
Действие: Опишите верное имя группы сразу после
ключевого слова CLUSTER. - ORA-00944: insufficient number of clustered columns
недостаточное число сгруппированных колонок
Причина: Была попытка создать таблицу с меньшим
числом сгруппированных колонок, чем было описано
в команде CREATE CLUSTER. Выражение CLUSTER команды
CREATE TABLE должно описывать все сгруппированные
колонки, определенные при создании группы. Используя
имя группы можно просмотреть все групповые колонки в
таблице словаря COL.
Действие: Опишите все имена колонок в команде
CREATE TABLE. - ORA-00945: specified clustered column does not exist
описанная групповая колонка не существует
Причина: Колонка, описанная в выражении оператора
CREATE TABLE не является колонкой данной таблицы.
Действие: Повторите, используя имя колонки таблицы. - ORA-00946: missing TO keyword
пропущено ключевое слово TO
Причина: Команда GRANT введена без ключевого слова
TO или использована неверная форма этой команды.
Действие: Проверьте синтаксис двух основных форм
команды GRANT ( предоставление доступа к базе данных
и предоставление привилегий). Вставьте ключевое слово
TO правильно в команду GRANT. - ORA-00947: not enough values
недостаточно значений
Причина: Опертор SQL требует двух одинаковых наборов
значений, а второй набор содержит меньшее число зна-
чений. Это может произойти и в случае, если в выраже-
ниях WHERE или HAVING вложенная SELECT находит меньшее
число колонок, как в : WHERE(A,B) IN (SELECT C FROM..)
Возможна ошибка и в операторе INSERT в котором выра-
жения VALUES или SELECT не содержат достаточно для
INSERT значений, как в:
INSERT INTO таблица (A,B) VALUES(‘C’).
Действие: Поверрьте численность каждого набора и
сделайте их равными по числу. - ORA-00948: ALTER CLUSTER statement no longer supported
опреатор ALTER CLUSTER более не поддерживается
Причина: Оператор ALTER CLUSTER удален
Действие: Для добавления данных из таблицы исполь-
зуйте следущий набор операторов SQL: CREATE TABLE
<новая_таблица> SELECT*FROM <старая_таблица> CLUSTER
<имя_группы> DROP <старая_таблица> и
RENAME TABLE <новая_таблица> <старая_таблица>. - ORA-00949: illegal reference to external database
неверная сноска на внешнюю базу данных
Причина:Это сообщение о внутренней ошибке,
которая не может произойти при нормальной работе .
Действие: Обратитесь к соответствуюшему наладочному
обеспечению с подробным описанием проблемы. - ORA-00950: invalid drop optio
неверная опция DROP
Причина: После команды DROP не было опции DROP
такой, как TABLE, VIEW, SYNONYM, CLUSTER, или SPACE.
Действие: Проверьте синтаксис команды и используй-
те верный формат опции DROP. - ORA-00951: cluster not empty
группа не является пустой
Причина: Команда DROP описывает не пустую группу.
Группа может быть удалена только в том случае, если
она не содержит таблиц. Удалить таблицу из группы
с помощью команды DROP TABLE.
Действие: Удалите из группы все таблицы и после
этого используйте команду DROP CLUSTER. - ORA-00952: missing GROUP keyword
пропущено ключевое слово GROUP
Причина: Группа неверно реализована.
Действие: От пользователя не требуется ни каких
действий. - ORA-00953: missing index name
—
пропущено имя индексаПричина: В командах CREATE, DROP, VALIDATE INDEX
имя индекса неверное или отсутствует.
Действие: Напечатайте верное имя индекса после
ключевого слова INDEX. Если вы желаете удалить или
исправить индекс, проверьте имя, просмотрев обзор
INDEXES. Если необходимо создать новый индекс, про-
верьте сначала синтаксис. - ORA-00954: missing INDENTIFIED keyword
пропущено ключевое слово INDENTIFIED
Причина: Команда GRANT CONNECTION была введена без
ключевого слова INDENTIFIED.
Действие: Вставьте ключевое слово INDENTIFIED после
имени пользователя. Формат команды следущий:GRANT
CONNECTION TO <список пользователей> INDETIFIED BY
<пароль списка>. - ORA-00955: name is already used by existing object
имя используется существующим объектом
Причина: Была попытка создать таблицу, обзор,
группу или синоним, которые уже есть. Каждое имя поль-
зовательской таблицы долно быть отличным от других
имен таблиц, обзоров, групп или синонимов, принадле-
жащих другим пользователям.Действие: Или введите уникальное имя таблицы, об-
зора,группы или синонима, или измените или удалите
существующее. - ORA-00956: invalid auditing optio
—
неверная опция контроляПричина: Была неверная опция проверки.
Действие: Проверьте синтаксис команды и повторирте
попытку с верной опцией. - ORA-00957: duplicate column name
дублирование имени колонки
Причина: Имя колонки было описано дважды в команде
CREATE или INSERT. Имя колонки в таблице, обзоре или
в группе должно быть уникальным.Действие: Замените в команде CREATE имя колонки
на новое уникальное. В команде INSERT удалите дубли-
рущее имена. - ORA-00958: missing CHECK keyword
—
пропущено ключевое слово CHECKПричина: Отсутствует CHECK сразу после ключевого
слова WHITH в выражении WITH CHECK OPTION оператора
CREATE VIEW.Действие: Проверьте синтаксис оператора SQL.
- ORA-00959: space definition name does not exist
—
имя области не существуетПричина: В команде A DROP SPACE описано несущест-
вующее имя области.Действие: Используйте существующие имена определе-
ния области. Для просмотра существующих имен выберите
SNAME из SPACES. - ORA-00960: invalid INITIAL value
—
неверное значение INITIALПричина: Было описано неверное значение номера
начальной datapage или indexpage в команде CREATE
SPACE. Это значение должно быть не менее 3.Действие: Введите значение INITIAL не меньшее 3.
- ORA-00961: invalid INCREMENT value
—
неверное значение INCREMENTПричина: Было описано неверное значение числа
шагов для datapage или indexpage. Значение шага
должно быть более 3.Действие: Введите значение INCREMENT болшее 3.
- ORA-00962: invalid PCTFREE value
—
неверное значение PCTFREEПричина: Неверное значение процента свободного
места было описано в определении SPACE. Это значение
долно находиться в диапазоне от 1: до 99.Действие: Введите значение PCTFREE в интервале
от 1: до 99. - ORA-00963: invalid SIZE value
неверное значение SIZE
Причина: Было описано неверное значение размера
логического блока в команде CREATE CLUSTER. Размер
логического блока используется для эффективного хра-
нения малых групп данных.Действие: Опишите допустимое значение размера логи-
ческого блока ( более 0). - ORA-00964: invalid space defenition name
—
неверное имя определения областиПричина: Было описано неверное имя области в коман-
де CREATE/DROP SPACE или в CREATE TABLE, или в команде
CREATE TABLE описано несуществующее имя области.Действие: Введите верное имя области. Допустимое
имя начинается с буквы, содержит не более 30: сим-
волов и состоит только из букв, цифр и спецсимволов $,
_ и #. Оно не должно быть зарезервированным словом.
Если ваше имя верное, возможно вы нечаянно удалили
определение области TEMP. - ORA-00965: space definition name already exists
—
имя определения области уже существуетПричина: В команде CREATE SPACE было использовано
существующее имя области. Имена определений областей
должны быть уникальными.Действие: Введите уникальное имя области.
- ORA-00966: missing TABLE keyword
—
пропущено ключевое слово TABLEПричина: Была использована команда LOCK и при этом
ключевое слово TABLE было с опечаткой, или пропущено,
или неверно расположено. Команда LOCK должна начи-
наться так: LOCK TABLE <имя таблицы> … .
Действие: Вставьте ключевое слово TABLE в соот-
ветствущее место. - ORA-00968: missing INDEX keyword
—
пропущено ключевое слово INDEXПричина: Была использована команда CREATE UNIQUE
и при этом ключевое слово INDEX было с опечаткой,
или пропущено, или неверно расположено .
Действие: Проверьте синтаксис и повторите попытку. - ORA-00969: missing ON keyword
—
пропущено ключевое слово OПричина: Была использована команда GRANT или CREATE
INDEX и при этом ключевое слово ON было с опечаткой,
или пропущено, или неверно расположено.Действие: Вставьте ключевое слово ON в соот-
ветствущее место. - ORA-00970: missing WITH keyword
—
пропущено ключевое слово WITHПричина: Ключевое слово START было использовано без
WITH. Оба ключевых слова необходимы в выражении
START WITH для запроса.Действие: Замените слово START на START WITH.
- ORA-00971: missing SET keyword
—
пропущено ключевое слово SETПричина: В команде UPDATE ключевое слово SET
было с опечаткой, или пропущено, или неверно распо-
ложено.Действие: Вставьте ключевое слово SET после имени
изменяемой таблицы. - ORA-00972: indentifier is too big
—
индентификатор слишком большойПричина: Размер имени объекта базы данных более
30: символов.(Объектами базы данных являются таблицы,
группы, обзоры, индексы, синонимы, области и имена
пользователей.Действие: Укоротите имя до максимум 30: символов.
- ORA-00973: invalid row count estimate
—
неверная оценка счета строкПричина: Величина счета строк, описанная в команде
CREATE INDEX является числом, меньшим 0.Действие: Опишите верное значение (большее чем 0).
- ORA-00974: invalid index block loading factor ( percentage )
—
неверный фактор загрузки блока индексов (процент)Причина: Процент назанятого объема, описанной в
команде CREATE INDEX, области не принадлежит интерва-
лу от 1: до 90%.Действие: Введите значение PCTFREE из диапазона от 1 до 90. По умолчанию — 10.
- ORA-00975: Date + date not allowed
—
неразрешается данные + данныеПричина: Попытка сложить вместе два поля данных.
Данные могут быть добавлены только к полям чисел, но
не к другим данным.Действие: Добавьте поле данных к полю чисел.
- ORA-00977: duplicate auditing optio
—
двойная опция контроляПричина: Та же самая опция контроля была описана
еще раз.Действие: Удалите лишнее описание контроля.
- ORA-00978: nested set function with out GROUP BY
—
вложенный групповая функция без GROUP BYПричина: Групповая функция (такая как MIN, MAX,
или AVG) была использована внутри другой групповой
функции (такой как MAX(COUNT(*))) без соответствую-
щего выражения GROUP BY.Действие: Или добавьте выражение GROUP BY или
удалите внешний уровень вложенности. - ORA-00979: not a GROUP BY expressio
выражение не принадлежит к GROUP BY
Причина: Предложение GROUP BY не содержит всех
выражений предложения SELECT. Выражения из SELECT,
не включенные в групповые функции (COUNT, SUM, AVG,
MAX, MIN ) должны быть перечислены в предложении
GROUP BY.Действие: Включите все выражения из SELECT, не
являющиеся аргументами групповых функций в предложе-
ние GROUP BY. - ORA-00980: synonym translation no longer valid
трансляции синонима более не доступна
Причина: Используемый вами синоним относился к таб-
лице, обзору или синониму, которые удалены или переи-
менованы.Действие: Замените синоним на имя таблицы, обзора,
синонима, для которых он предназначался. Или заново
создайте синоним для верных таблиц, обзоров или сино-
нимов. - ORA-00981: cannot mix table and system-wide auditing options
нет возможности совместить опцию контроля ширины таблицы
и системыПричина: Одновременно опция ширины и таблицы и
системы описаны в одном операторе AUDIT.Действие: Исправьте оператор.
- ORA-00982: missing plus sign — пропущен знак плюс
Причина: При присоединении после левой скобки нет
знака плюс (+). При присоединении левая (открывающая)
скобка интерпритируется как описывающая присоединение
и ожидается знак плюс. Для описания присоединения к
колонке, за описанием колонки следует поставить знак
плюс, заключенный в скобки (+).Действие: Исправьте синтаксис SQL.
- ORA-00984: column not allowed here — колонки здесь не употребимы
Причина: Имя колонки было использовано там, где это запрещено,
например в предложении VALUES оператора INSERT.
Действие: Проверьте синтаксис команды и используйте имена колонок только там, где это допустимо. - ORA-00985: invalid program name — неверное имя программы
Причина: Это свойство не реализовано.
Действие: Не требуется ни каких действий пользователя. - ORA-00986: missing or invalid group name(s) — пропущено или неверное имя группы
Причина: Это свойство не реализовано.
Действие: Не требуется ни каких действий пользователя. - ORA-00987: missing or invalid user name(s)
—
пропущено или неверное имя пользователяПричина: Имя пользователя не было описано в команде
GRANT или одно из описанных имен неверное. Верные
имена пользователей должны описываться после слова
TO в команде GRANT. Допустимое имя пользователя
начинается с буквы, содержит не более 30: символов
и состоит только из букв, цифр и спецсимволов $,
_ и #. Оно не должно быть зарезервированным словом.Действие: Опишите верное имя пользователя (или
список пользователей ) после ключевого слова TO в
команде GRANT. - ORA-00988: missing or invalid password(s)
—
пропущен или неверный пароль(и)Причина: В команде GRANT описано имен пользователей
больше, чем паролей. Допустимый пароль должен быть
описан для каждого пользователя, перечисленного в
команде GRANT.Действие: Введите правильный пароль для каждого
пользователя. - ORA-00989:
too many passwords for user names given — слишком много паролей для пользователей введеноПричина: Паролей больше, чем было описано имен поль-
зователей в команде GRANT. Только один пароль должен
вводиться для каждого пользователя, перечисленного в
команде GRANT.Действие: Введите одинаковое количество пользователей и паролей.
- ORA-00990: missing or invalid privilege — пропущена или неверная привелегия
Причина: В команде для привелегий GRANT не было
описано никаких привелегий или одна из них неверная.Действие: Введите одну или более верных привелегий.
Допустимы следущие привелегии: SELECT, INSERT, DELETE,
UPDATE, ALTER, INDEX, DROP, CLUSTER и ALL. Более чем
одну привелегию можно предоставить введя их в списке
через запятую(,) или описывая словом ALL предоставлять
все привелегии. - ORA-00991:
unrecognizable format for GRANT command — неопознанный формат команды GRANTПричина: Введена неправильная форма команды GRANT.
Действие: Проверьте синтаксис команды.Существует два
типа команды GRANT. Первый тип используется для опре-
деления доступа пользователей к базе данных и должен
иметь следущий формат: GRANT CONNECT/RESOURCE/DBA TO
<имя пользователя> INDENTIFIED BY <пароль>. По крайней
мере одно из ключевых слов CONNECT, RESOURCE или DBA
должно присутствовать. Второй тип используется для
предоставления превелегий объектам базы данных и
и имеет формат: GRANT <список привелегий> ON <обзор/
таблица> TO < индентификатор пользователя>/PUBLIC. - ORA-00992:
unrecognizable format for REVOKE command — неопознанный формат команды REVOKE
Причина: Введена неправильная форма команды REVOKE.
Действие: Проверьте синтаксис команды и повторите ее. - ORA-00993: missing GRANT keyword — пропущено ключевое слово GRANT
Причина: Ключ WITH был описан в конце команды GRANT
без ключа GRANT.Чтобы предоставить привелегии пользо-
вателю и разрешение на предоставление их другим поль-
зователям, следует использовать ключ WITH GRANT OPTIO
в конце команды GRANT.Действие: Замените ключевое слово WITH на WITH GRANT OPTION.
- ORA-00994: missing OPTION keyword — пропущено ключевое слово OPTIO
Причина: Был использован ключ WITH GRANT в конце команды GRANT без слова OPTION.
Действие: Замените ключ WITH GRANT на WITH GRANT OPTION. - ORA-00995:
missing or invalid synonym indentifier — пропущен или неверный синоним индентификатора
Причина: В командах CREATE или DROP SYNONYM имя синонима или было пропущено или неверное.
Действие: Проверьте опечатки и синтаксис команды.
Правильное имя синонима должно следовать сразу за ключом SYNONYM в обеих командах.
Допустимое имя синонима начинается с буквы, содержит не более 30 символов
и состоит только из букв, цифр и спецсимволов $, _ и #.
Оно не должно быть зарезервированным словом. - ORA-00996:
the concatenate operator is ¦¦ not ¦ — оператором конкатенации является ||, а не |
Причина: Единичный штрих (|) был понят как попытка описать конкатенацию,
но оператор конкатенации состоит из двух штрихов (||).
Действие: Введите двойной штрих для операции конкатенации
или удалите одиночный, если конкатенация не нужна. - ORA-00997:
illegal use of long datatype (недопустимое использование типа данных LONG).
Причина: Вы использовали тип данных LONG, используемый для хранения данных размером более 240 символов,
в функции или в предложениях WHERE, GROUP BY, ORDER BY.
Значение LONG может использоваться только в предложении SELECT.
Действие: Удалите это поле из функции или предло жения. - ORA-00998:
must name this expression with a column label (это выражение должно называться с псевдонима).
Причина: В команде CREATE VIEW была использована
функция или выражение, но не было описано соответствущее имя колонки.
Когда для обзора используется выражение или функция,
все имена колонок и обзоров должны правильно быть перечислены в команде CREATE VIEW.
Действие: Введите все имена колонок обзора в
скобках после имени обзора. - ORA-00999:
invalid view name (неверное имя представления).
Причина: В команде CREATE VIEW пропущено или неверное имя обзора.
Действие: Введите сразу за CREATE VIEW верное имя обзора.
Допустимое имя обзора начинается с буквы, содержит не более 30 символов
и состоит только из букв, цифр и спецсимволов $,_ и #.
Оно не должно быть зарезервированным словом.
На правах рекламы (см.
условия):
На русском языке: ошибки Oracle, коды оракловых ошибок;
На английском языке: ORA-00000: — ORA-00999.
|
Страница обновлена 28.09.2022
|
|
|
Do you need to find out more information about your errors and exceptions in PL/SQL?
You can use the SQLCODE and SQLERRM functions to do that. Learn how the functions work and see some examples in this article.
Purpose of the SQLCODE and SQLERRM Functions
The SQLCODE function returns the number code of the most recent exception.
This number code is an ANSI-standard code, which means it is the same for all relational databases. It is different from the ORA codes, which you may also get when working with Oracle databases.
The SQLERRM function returns the error message that relates to the error number provided.
This function is similar to the SQLCODE function, where the only real useful place for it is inside an exception handler in PL/SQL. We’ll see more on this later in the article.
SQLCODE Syntax and Parameters
The SQLCODE function is pretty simple:
SQLCODE
There are no parameters for the Oracle SQLCODE function.
SQLERRM Syntax and Parameters
The syntax of this function is:
SQLERRM ( error_number )
The parameters of the SQLERRM function are:
- error_number (optional): A valid Oracle error number.
Now, it seems like a simple function, but there are some things to keep in mind:
- If the error_number is omitted, then it returns the error message associated to the current value of SQLCODE.
- If it is used outside an exception handler without a parameter, SQLERRM always returns a “normal, successful completion” message.
- The message returned begins with the Oracle error code.
- For user-defined exceptions, Oracle returns the message “user-defined exception”, unless you have specified your own message using the pragma EXCEPTION_INIT.
- If a value of 0 is used as the error_number, SQLERRM returns a “normal, successful completion” message.
- If a positive number other than 100 is used, then SQLERRM returns a “user-defined exception” message.
- If a value of 100 is used, SQLERRM returns “ORA-01403: no data found”.
How Should I Use the SQLCODE and SQLERRM Functions?
The best way to use the SQLCODE and SQLERRM functions is inside an exception handler in PL/SQL.
This is where you handle any errors that occur. If you use the SQLCODE function or SQLERRM function outside the error handler, it will return 0 and won’t be of use to you.
It’s also a good idea to assign the SQLCODE to a variable and then use that variable in your code.
The SQLERRM function is similar. It returns the error message associated with the most recent error. It is common practice to use both SQLCODE and SQLERRM together, as SQLERRM describes what the error is, but it’s up to you.
Why Am I Getting SQLERRM Invalid Identifier?
Sometimes, you might get an SQLERRM invalid identifier message in your SQL:
ORA-00904: : invalid identifier
This is often caused by a function being called that does not exist, or that needs the package to be recompiled, or the function is not accessible by the current user.
Can I Log the Line Number Using Oracle SQLERRM?
Yes, you can, but there’s no simple way to do it.
You can use the DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_BACKTRACE); function to output the line number, which looks something like this:
ORA-06512: at line 12
Then, to store it, you’ll need to perform some string manipulation on DBMS_UTILITY.FORMAT_ERROR_BACKTRACE.
What Is The SQLERRM Length?
The maximum length of the SQLERRM function return value is 512 characters.
This is useful if you want to store the value in a table when you log an error.
This page here shows a list of many SQLCODE values. The SQLCODE of 000 is the default value and indicates success, but other messages are also not failure messages, so you shouldn’t always test for when the message is 000.
Examples of the SQLCODE Function
Here are some examples of the Oracle SQLCODE function. I find that examples are the best way for me to learn about code, even with the explanation above.
Example 1 – Output Error
This example PL/SQL code shows you how to output an error code.
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('An error was encountered: '||SQLCODE||' - '||SQLERRM);
END;
You can see that I have used the SQLCODE function as well. There is no parameter of the SQLERRM function, which means it uses the value of the SQLCODE function.
Example 2 – Raise Exception
This example PL/SQL code shows you how to raise an exception from the error that was found
EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20010, 'An error was encountered: '||SQLCODE||' - '||SQLERRM);
END;
Example 3 – Insert Into Table
This example PL/SQL code shows you how to insert the error message into a table for logging purposes. You would change the value of ‘thisFunction’ to the name of the function that this code is in.
EXCEPTION
WHEN OTHERS THEN
errorcode := SQLCODE;
errormessage := SQLERRM;
INSERT INTO error_log (error_number, error_message, function_name)
VALUES (errorcode, errormessage, 'thisFunction');
END;
Example 4 – Output Specific Message
This example uses a parameter for the SQLERRM function and outputs the result.
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('An error was encountered: '||SQLERRM(-20010));
END;
You can find a full list of Oracle SQL functions here.
Lastly, if you enjoy the information and career advice I’ve been providing, sign up to my newsletter below to stay up-to-date on my articles. You’ll also receive a fantastic bonus. Thanks!