Oracle select into данные не найдены

Обновлено: 07.07.2024

Маленькое руководство по отлавливанию ошибок в Oracle PLSQL.
Описание как использовать в Oracle (PLSQL) функции SQLERRM и SQLCODE для отлова ошибок EXCEPTION, с описанием синтаксиса и примером.

Функция SQLCODE возвращает код ошибки связанный с последним возникшим исключением (ошибкой)
Функция SQLERRM — не имеет параметров.

Обычно обработка исключений EXCEPTION выглядит следующим образом:


Варианты основных возможных ошибок:

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
Вы пытаетесь открыть курсор который уже открыт.

если инструкция SELECT INTO не возвращает по крайней мере одну строку, Ora-01403 выбрасывается.

для каждой другой СУБД я знаю, что это нормально для выбора. Только Oracle обрабатывает SELECT таким образом.

почему?

на мой взгляд, вам не нужно это исключение. Это слишком накладно. Иногда это удобно, но вам нужно написать целый блок BEGIN, EXCEPTION, WHEN, END.

есть ли существенные причины я не видишь?

блок исключений не нужны, вы можете использовать его или нет, в зависимости от контекста.

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

В общем, единственными исключениями, которые вы должны поймать, являются ожидаемые исключения (т. е. это не должно быть стандартом для ловли всех ORA-01403 или всех исключений в этом отношении).

но нам все равно нужно ответить на вопрос "почему возникает исключение в случае, когда SELECT не имеет данных для извлечения".

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

вероятно, IMHO, что проверка на SQLCODE = 100 будет часто пропускаться. Имеющий исключение, поднятое баранами, прямо в нос, что А) важное условие (данные не найдены) произошло, и Б) на это не было сделано никакого учета. IMO, имеющий PL / SQL engine, вызывает исключение, лучше, чем программа весело продолжает свой путь в предположении, что данные были получены, когда на самом деле это не так, что может привести ко всем видам других, чем веселых проблем.

поделиться и наслаждаться.

вы можете попробовать использовать MIN для предложения исключения использования.

тогда фиктивная переменная будет NULL

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

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

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

потому что неясно, что должен делать движок PL/SQL - должен ли он выйти из блока? Должен ли он нажимать с NULL в переменной? Что делать, если в следующем блоке вы попытаетесь вставить это в столбец NOT NULL, как он должен сообщить о местоположении ошибки? Сделав это исключением, вы должны быть откровенны.

вы также можете использовать SQL макс или мин функции. Если строка не возвращается, то эти функции вернут NULL.

например: Выберите макс(колонка 1) В переменные из таблицы Где Column1 = 'Value';

на макс функция вернет максимальное значение или, если строка не будет возвращена, она вернет NULL.

1) Если выполнить вручную селект с тем hdebet,
которое туда приходит (проверял), то возвращается 1 строка
(как и должно быть)
2) если выполнить процедуру на клиенте через ADo.ORaOleDB,
то летит ошибка

ORA-01403: no data found
ORA-01403: no data found
ORA-06512: at "FEB_WORK.FE_SP_FM_CHECKOPERACC", line 89
ORA-06512: at "FEB_WORK.FE_SP_FM_INSERTSALDO", line 11
ORA-06512: at "FEB_WORK.FE_T_OPER_IN_CUS", line 2
ORA-04088: error during execution of trigger 'FEB_WORK.FE_T_OPER_IN_CUS'
ORA-06512: at "FEB_WORK.FE_SP_INSERT", line 33
ORA-06512: at line 1


3) Если раскомментировать raise в конце процедуры,
то просто выводится значение hdebet в ошибке
(причем, чтобы оптимизатор не соптимизировал что-то,
я выводил таку переменную значениекоторой невозможно
определить без выполнения всей процедуры)


ГДЕ ГРАБЛИ ГОСПОДА . Где они родимые спрятались?


Еще есть такая лажа.


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

ORA-03113 end-of-file on communication channel

Здравствуйте, kto-to, Вы писали:

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

Этот селект — 89-я строка процедуры?

Протрассируйте сессию с вызовом этой процедуры. Вся ситуация, да и двойной no data found подталкивают к мысли, что втихаря выполняется еще какой-то код, в котором, собственно, и зашита проблема.

Попробуйте эквивалентные изменения, например, перепишите select into на for — увидите возвращаемую (пустую) выборку либо тот же no data found?

Не понял? Это как?

Здравствуйте, kto-to, Вы писали:

KT>Глючит именно из софтины. Я проверял, что, например, глюка с коммитом нет при выполнении в
KT>PL\SQL Developer

Аудит? FGAC? Это и надо выяснить — кто его выполняет. Для этого в первую очередь и делается трассировка — она покажет куда более точную картину происходящего.

S>>Попробуйте эквивалентные изменения, например, перепишите select into на for — увидите возвращаемую (пустую) выборку либо тот же no data found?
KT>Не понял? Это как?

Напишите вместо select into цикл for по курсору, в котором присваивайте полям значения из курсора. Если все равно получите no data found — это железно докажет, что Ваш код тут самым немыслимым боком не при чем.

Здравствуйте, kto-to, Вы писали:

KT>1) Если выполнить вручную селект с тем hdebet,
KT>которое туда приходит (проверял), то возвращается 1 строка
KT>(как и должно быть)
KT>2) если выполнить процедуру на клиенте через ADo.ORaOleDB,
KT>то летит ошибка

А как байндится hdebet (RAW) на клиенте? Есть подозрение, что условие "where c.fe_fld_pkguid = hdebet" не выполняется из-за неверной передачи hdebet. Попробуй в том же клиентском коде на ADO, который вызывает процедуру, заменить вызов процедуры на простой

и сделай bind переменной bound_hdebet на то же значение, что передается в процедуру.

Если инструкция SELECT INTO не возвращает хотя бы одну строку, ORA-01403 выбрасывается.

Для каждой другой СУБД я знаю, что это нормально для SELECT.
Только Oracle рассматривает SELECT INTO так.

Почему?

По-моему, вам действительно не нужно это исключение. Это слишком много накладных расходов.
Иногда это удобно, но вам нужно написать целые BEGIN, EXCEPTION, WHEN, END Block.

Есть ли какие-то существенные причины, которые я не вижу?

Блок исключений не нужен, вы можете использовать его или нет, в зависимости от контекста.

Здесь вы активно игнорируете исключение (процедура вернется успешно), но большую часть времени, если вы выполняете SELECT INTO, вы хотите, чтобы он вышел из строя, если он не возвращает строку, рассмотрим:

В общем, единственными исключениями, которые вы должны уловить, являются ожидаемые исключения (т.е. это не должно быть стандартом, чтобы поймать все ORA-01403 или все исключения в этом отношении).

вероятно, ИМХО, что проверка на SQLCODE = 100 будет часто пропущена. Имея исключение, поднятые барабаны прямо вверх по вашему носу, что A) произошло важное условие (данные не найдены), и B) НИКАКОЕ ПОЛОЖЕНИЕ НЕ СДЕЛАЛОСЬ ДЛЯ ЭТОГО. ИМО, имеющий механизм PL/SQL, создает исключение, лучше, чем программа продолжает весело на своем пути в предположении, что данные были восстановлены, когда на самом деле это не так, что может привести к разным проблемам, отличным от других.

Поделитесь и наслаждайтесь.

Вы можете попробовать использовать MIN, чтобы избежать использования предложения EXCEPTION.

тогда фиктивная переменная будет NULL

Поскольку вы выполняете SELECT INTO, для которого требуется ровно одна строка (больше строк также будет ошибкой).

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

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

Вы также можете использовать функции sql MAX или MIN. Если ни одна строка не возвращается, эти функции возвращают NULL.

Функция MAX вернет максимальное значение или если строка не будет возвращена, она вернет NULL.

Функция MAX работает, но не выдает ошибку. ORA-01403 работает, когда NULL возвращается, выбрав INTO.

Читайте также: