2009-08-10 1 views
37
SET SERVEROUTPUT ON 
DECLARE 
    v_student_id NUMBER := &sv_student_id; 
    v_section_id NUMBER := 89; 
    v_final_grade NUMBER; 
    v_letter_grade CHAR(1); 
BEGIN 
    SELECT final_grade 
    INTO v_final_grade 
    FROM enrollment 
    WHERE student_id = v_student_id 
    AND section_id = v_section_id; 

    CASE -- outer CASE 
     WHEN v_final_grade IS NULL THEN 
      DBMS_OUTPUT.PUT_LINE ('There is no final grade.'); 
     ELSE 
      CASE -- inner CASE 
       WHEN v_final_grade >= 90 THEN v_letter_grade := 'A'; 
       WHEN v_final_grade >= 80 THEN v_letter_grade := 'B'; 
       WHEN v_final_grade >= 70 THEN v_letter_grade := 'C'; 
       WHEN v_final_grade >= 60 THEN v_letter_grade := 'D'; 
       ELSE v_letter_grade := 'F'; 
      END CASE; 

      -- control resumes here after inner CASE terminates 
      DBMS_OUTPUT.PUT_LINE ('Letter grade is: '||v_letter_grade); 
    END CASE; 
    -- control resumes here after outer CASE terminates 
END; 

приведенный выше код я взял из книги Oracle PL-SQL на примере четвёртое издание 2009 моя проблема, когда я ввести идентификатор студента, отсутствующий в таблице она возвращает меня следующие ошибкиPL/SQL блок Проблема: Нет данных

 
Error report: ORA-01403: no data found 
ORA-06512: at line 7 
01403. 00000 - "no data found" 
*Cause:  
*Action: 

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

пожалуйста, помогите мне ...

спасибо заранее

+0

Есть ли вероятность форматирования вашего PL SQL как кода? – pjp

+0

Теперь выглядит красиво и красиво :) – pjp

ответ

72

Когда вы выбираете INTO переменной и нет возвращенных записей, вы должны получить ошибку NO DATA FOUND. Я считаю, что правильным способом написания вышеуказанного кода было бы обернуть инструкцию SELECT собственным блоком BEGIN/EXCEPTION/END. Пример:

... 
v_final_grade NUMBER; 
v_letter_grade CHAR(1); 
BEGIN 

    BEGIN 
    SELECT final_grade 
     INTO v_final_grade 
     FROM enrollment 
    WHERE student_id = v_student_id 
     AND section_id = v_section_id; 

    EXCEPTION 
     WHEN NO_DATA_FOUND THEN 
     v_final_grade := NULL; 
    END; 

    CASE -- outer CASE 
     WHEN v_final_grade IS NULL THEN 
     ... 
2

Ваше SELECT утверждение не находит данные, которые вы ищете. То есть в таблице ENROLLMENT нет записей с данными STUDENT_ID и SECTION_ID. Вы можете попробовать поставить некоторые операторы DBMS_OUTPUT.PUT_LINE перед запуском запроса, распечатав значения v_student_id и v_section_id. Они не могут содержать то, что вы ожидаете от них.

1

Существует альтернативный подход, который я использовал, когда я не мог полагаться на EXCEPTION блок в нижней части моей процедуры. У меня были переменные, объявленные в начале:

my_value VARCHAR := 'default'; 
number_rows NUMBER := 0; 
. 
. 
. 
SELECT count(*) FROM TABLE INTO number_rows (etc.) 

IF number_rows > 0 -- Then obtain my_value with a query or constant, etc. 
END IF; 
0

Эти данные не найдены, потому что мы используем некоторый тип данных.

как выберите EmpId в v_test

выше EmpId и v_test должен быть тип номера, то только данные будут сохранены.

Так что следите за типом данных при получении этой ошибки, возможно, это поможет.