1. ホーム
  2. sql

[解決済み] PL/SQLブロックの問題:データが見つからないエラー

2022-03-11 18:13:50

質問

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 by Example, 4th Edition 2009" を入力するときに問題があります。 student_id テーブル内に存在しない場合、次のようなエラーが返されます。

エラー報告です。ORA-01403: データが見つかりません
ORA-06512: 7 行目
01403. 00000 - "no data found"
*原因    
*Action:

しかし、この本によると、NULL値を返して、それからケースの流れに従うべきでした。

どのように解決するのですか?

変数の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
      ...