Почему 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 Block.
Есть ли какие-то существенные причины, которые я не вижу?
Ответы
Ответ 1
Блок исключений не нужен, вы можете использовать его или нет, в зависимости от контекста.
Здесь вы активно игнорируете исключение (процедура вернется успешно), но большую часть времени, если вы выполняете 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 или все исключения в этом отношении).
Ответ 2
Но нам все равно нужно ответить на вопрос "почему исключение выбрано в случае, когда SELECT не имеет данных для извлечения".
Я считаю, что это сделано, потому что это обычная ситуация, которая в противном случае может быть упущена. Написание кода, как если бы он всегда ожидал найти данные, - это обычная вещь, и если мы должны были провести проверку ошибок, например
SELECT <something...>
IF SQLCODE = 100 THEN -- No data found
<no-data handler>
END IF
вероятно, ИМХО, что проверка на SQLCODE = 100 будет часто пропущена. Имея исключение, поднятые барабаны прямо вверх по вашему носу, что A) произошло важное условие (данные не найдены), и B) НИКАКОЕ ПОЛОЖЕНИЕ НЕ СДЕЛАЛОСЬ ДЛЯ ЭТОГО. ИМО, имеющий механизм PL/SQL, создает исключение, лучше, чем программа продолжает весело на своем пути в предположении, что данные были восстановлены, когда на самом деле это не так, что может привести к разным проблемам, отличным от других.
Поделитесь и наслаждайтесь.
Ответ 3
Вы можете попробовать использовать MIN, чтобы избежать использования предложения EXCEPTION.
SELECT MIN(dummy)
INTO dummy
FROM dual
WHERE dummy = 'Y';
тогда фиктивная переменная будет NULL
Ответ 4
Поскольку вы выполняете SELECT INTO, для которого требуется ровно одна строка (больше строк также будет ошибкой).
Если вы можете иметь одну или никакую строку, вы можете использовать курсор.
Это не задание базы данных, чтобы решить, что недостающая строка не является ошибкой, и просто установите значение null.
Ответ 5
Вы также можете использовать функции sql MAX или MIN. Если ни одна строка не возвращается, эти функции возвращают NULL.
Например:
Выберите МАКС. (столбец1)
В переменную
Из таблицы
Где Column1 = 'Value';
Функция MAX вернет максимальное значение или если строка не будет возвращена, она вернет NULL.
Ответ 6
Потому что неясно, что должен делать движок PL/SQL - должен ли он выйти из блока? Должен ли он нажимать на NULL в переменной? Что делать, если в следующем блоке вы пытаетесь вставить его в столбец NOT NULL, как он должен сообщить о месте ошибки? Из-за исключения это заставляет вас быть явным.
Ответ 7
Функция MAX работает, но не выдает ошибку. ORA-01403 работает, когда NULL возвращается, выбрав INTO.