Почему 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, как он должен сообщить о местонахождении ошибки? Сделав это исключение, вы должны быть откровенным об этом.

Другие вопросы по тегам