Почему no_data_found ORA-01403 является исключением в Oracle?
Если инструкция SELECT INTO не возвращает хотя бы одну строку, ORA-01403 выбрасывается.
Для любой другой СУБД я знаю, что это нормально для SELECT. Только Oracle рассматривает SELECT INTO таким образом.
CREATE OR REPLACE PROCEDURE no_data_proc IS
dummy dual.dummy%TYPE;
BEGIN
BEGIN
SELECT dummy
INTO dummy
FROM dual
WHERE dummy = 'Y';
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('Why is this needed?');
END;
END no_data_proc;
Зачем?
На мой взгляд, вам не нужно это исключение на самом деле. Это слишком много накладных расходов. Иногда это удобно, но вы должны написать целый блок BEGIN, EXCEPTION, WHEN, END.
Есть ли какие-то существенные причины, которые я не вижу?
6 ответов
Блок исключений не нужен, вы можете использовать его или нет, в зависимости от контекста.
Здесь вы активно игнорируете исключение (процедура вернется успешно), но большую часть времени, если вы делаете SELECT INTO, вы хотите, чтобы оно завершилось ошибкой, если оно не возвращает строку, рассмотрите:
PROCEDURE update_employee_salary (p_empno) IS
l_salary NUMBER;
BEGIN
SELECT sal INTO l_salary FROM emp WHERE empno = p_empno FOR UPDATE;
/* do something with emp data */
END;
Здесь я хочу, чтобы моя функция не работала, если она вызывается с empno
это не существует в таблице EMP. Я мог бы поймать исключение, чтобы вызвать значимое сообщение об ошибке (с raise_application_error
) но большую часть времени я доволен ORA-01403.
В общем, единственными исключениями, которые вы должны поймать, являются ожидаемые исключения (то есть это не должно быть стандартом для перехвата всех ORA-01403 или всех исключений по этому вопросу).
Но нам все еще нужно ответить на вопрос "почему возникает исключение в случае, когда SELECT не имеет данных для извлечения".
Я считаю, что это сделано, потому что это обычная ситуация, которую в противном случае можно было бы упустить из виду. Написание кода так, как будто он всегда ожидает найти данные, является обычным делом, и если мы должны были включить проверку ошибок, такую как
SELECT <something...>
IF SQLCODE = 100 THEN -- No data found
<no-data handler>
END IF
вполне вероятно, что ИМХО проверка на SQLCODE = 100 будет часто пропускаться. Возникновение исключения приводит к тому, что A) возникло важное условие (данные не найдены), и B) НИКАКОЕ ПРЕДОСТАВЛЕНИЕ НЕ СДЕЛАНО ДЛЯ ЭТОГО. IMO с механизмом PL/SQL вызывает исключение лучше, чем если бы программа продолжала весело продолжать свой путь, предполагая, что данные были извлечены, хотя на самом деле их не было, что может привести к всевозможным, кроме веселых, проблемам.
Поделитесь и наслаждайтесь.
Вы можете попробовать использовать MIN, чтобы избежать использования предложения EXCEPTION.
SELECT MIN(dummy)
INTO dummy
FROM dual
WHERE dummy = 'Y';
тогда фиктивная переменная будет NULL
Потому что вы делаете SELECT INTO, который требует ровно одну строку (больше строк также будет ошибкой).
Если у вас может быть одна строка или нет, вы можете использовать курсор.
Задача базы данных - не решать за вас, что пропущенная строка не является ошибкой, а просто установить значение в ноль.
Вы также можете использовать функции sql MAX или MIN. Если ни одна строка не возвращается, то эти функции будут возвращать NULL.
Например: выберите MAX(столбец1) в переменную из таблицы, где столбец1 = "значение";
Функция MAX вернет значение Maximum или, если строка не будет возвращена, то вернет NULL.
Функция MAX работает, она не выдает ошибку ORA-01403 работает, когда NULL возвращается при выборе INTO
Потому что не ясно, что должен делать механизм PL/SQL - должен ли он выйти из блока? Должен ли он нажимать с NULL в переменной? Что если в следующем блоке вы попытаетесь вставить это в столбец NOT NULL, как он должен сообщить о местонахождении ошибки? Сделав это исключение, вы должны быть откровенным об этом.