Как я могу устранить ошибку PL/SQL: Statement ignored?

Я новичок в PL/SQL и пытаюсь написать процедуру. Процедура будет запрошена с номером школы и курсом, midterm_not, final_not, будет показано среднее значение, но промежуточные и итоговые оценки будут рассчитаны в%. Если ему меньше 60, он будет окончен и пройден.

set serveroutput on;
CREATE OR REPLACE PROCEDURE student_grade(
        p_school_no IN lessons.school_number%type,
        p_lesson OUT lessons.lesson_name%type,
        p_midterm_1 OUT lessons.midterm_notu_1%type,
        p_midterm_2  OUT lessons.midterm_notu_2%type,
        p_final OUT lessons.final_notu%type,
        p_average OUT NUMBER
    )
    IS
    BEGIN
    SELECT
    d.lesson,
    d.midterm_notu_1,
    d.midterm_notu_2,
    d.final_notu
    INTO
        p_lesson,
        p_midterm_1,
        p_midterm_2,
        p_final
    FROM lessons d
    WHERE d.shool_number = p_school_no
    p_average := (((d.midterm_notu_1 * 25)/100) + ((d.midterm_notu_2 * 30)/100) + ((d.final_notu * 45)/100));
    END;
   
    DECLARE
    v_school_no lessons.school_number%type := 20201754;
    v_lesson lessons.lesson_name%type;
    v_midterm_1 lessons.midterm_notu_1%type;
    v_midterm_2  lessons.midterm_notu_2%type;
    v_final lessons.final_notu%type;
    v_average NUMBER;
    BEGIN
    student_grade(  
        v_lesson,
        v_midterm_1,
        v_midterm_2  ,
        v_final,
        v_average );
    DBMS_OUTPUT.put_line ('Student Grade');
    DBMS_OUTPUT.put_line ('School Number: ' ||v_school_no);
    DBMS_OUTPUT.put_line ('Midterm 1: ' || v_midterm_1);
    DBMS_OUTPUT.put_line ('Midterm 2: ' || v_midterm_2  );
    DBMS_OUTPUT.put_line ('Final: ' || v_final);
    DBMS_OUTPUT.put_line ('Average: ' || v_average );
    END;

Я сделал что-то подобное, когда запустил процедуру, в которой говорится "Procedure student_grade compiled" но когда я пытаюсь запустить DECLARE частично это дает такую ​​ошибку;

Error report -
ORA-06550: line 9, column 5:
PLS-00905: SYSTEM.STUDENT_GRADE object is invalid
ORA-06550: line 9, column 5:
PL/SQL: Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.

Проблема в p_average:= Может ли кто-нибудь помочь мне с этими проблемами?

2 ответа

Решение

Вы почти все сделали нормально. Немного о процедуре,

Выполните приведенную ниже команду (возможно, вы пропустили ошибку)

ALTER PROCEDURE student_grade COMPILE;
Warning: Procedure altered with compilation errors

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

чтобы присвоить какое-либо значение параметру OUT, вам не нужно использовать SET. Допускается только присваивание с использованием оператора присваивания. Смотри ниже

CREATE OR REPLACE PROCEDURE student_grade
(
   p_school_no IN lessons.school_number%TYPE
  ,p_lesson    OUT lessons.lesson_name%TYPE
  ,p_midterm_1 OUT lessons.midterm_notu_1%TYPE
  ,p_midterm_2 OUT lessons.midterm_notu_2%TYPE
  ,p_final     OUT lessons.final_notu%TYPE
  ,p_average   OUT NUMBER
) IS
BEGIN
   SELECT d.lesson
         ,d.midterm_notu_1
         ,d.midterm_notu_2
         ,d.final_notu
   INTO   p_lesson
         ,p_midterm_1
         ,p_midterm_2
         ,p_final
   FROM   lessons d
   WHERE  d.shool_number = p_school_no;
   --assign to the output variable for average
   p_average := (((d.midterm_notu_1 * 25) / 100) + ((d.midterm_notu_2 * 30) / 100) + ((d.final_notu * 45) / 100));
END;
/

Я считаю, что из-за ошибки в процедуре вы не смогли протестировать, после внесения вышеуказанных изменений она должна работать.

Вы также можете протестировать его с помощью анонимного блока PL/SQL вместо окна команд SQL, что было бы проще. Например

DECLARE
    --assign the input directly here in the declare section
    v_school_no lessons.school_number%type := 10;
    v_lesson lessons.lesson_name%type;
    v_midterm_1 lessons.midterm_notu_1%type;
    v_midterm_2  lessons.midterm_notu_2%type;
    v_final lessons.final_notu%type;
    v_average NUMBER;
BEGIN
    -- call the procedure
    student_grade(  
        v_lesson,
        v_midterm_1,
        v_midterm_2  ,
        v_final,
        v_average );
    DBMS_OUTPUT.put_line ('Student Grade');
    DBMS_OUTPUT.put_line ('School Number: ' ||v_school_no);
    DBMS_OUTPUT.put_line ('Midterm 1: ' || v_midterm_1);
    DBMS_OUTPUT.put_line ('Midterm 2: ' || v_midterm_2  );
    DBMS_OUTPUT.put_line ('Final: ' || v_final);
    DBMS_OUTPUT.put_line ('Average: ' || v_average );
END;
/

Сообщите мне, если это решит вашу проблему;


ПЕРЕСМОТРЕННЫЙ ОТВЕТ О КОНКРЕТНОЙ ПРОБЛЕМЕ ИСПОЛЬЗОВАНИЯ И ИСПОЛЬЗОВАНИЯ ИНСТРУМЕНТА

Я настоятельно рекомендую / предлагаю вам изучить документацию PL/SQL перед тем, как продолжить выполнение следующего задания. Это поможет вам понять возникающие ошибки и исправить их. Также есть много видеороликов об инструменте SQL Developer, как их эффективно использовать. Проверьте их тоже.

Возвращаясь к проблеме, которую я пробовал на своей машине, в скрипте есть много проблем, которые мне приходилось исправлять одно за другим, просматривая сообщения об ошибках. Пожалуйста, найдите пункты и окончательное решение, которые должны работать, иначе я закончу.

Проблемы: есть отличия в названиях столбцов в таблице от написанного вами кода

  1. WHERE d.shool_number = p_school_no; -> shool_number не существующий столбец, вероятно, d.school_number
  2. v_lesson lessons.lesson_name%type; -> фактический столбец lesson и нет lesson_name. Я могу сказать это из вашего пункта select в процедуре
  3. p_lesson OUT lessons.lesson_name%type, -> то же, что и в пункте 2
  4. p_average := (((d.midterm_notu_1 * 25)/100) + ((d.midterm_notu_2 * 30)/100) + ((d.final_notu * 45)/100)); - нельзя ссылаться на столбцы таким образом, что это значит с "d." где код не знает, к чему он относится. d вы использовали в запросе выбора как псевдоним таблицы lessons и с помощью оператора select заканчивается область действия dзаканчивает там сам. Поскольку вы уже перенесли значения в выходные переменные, такие какp_midterm_1, p_midterm_2, p_finalиспользуйте их вместо них.
  5. Кроме того, убедитесь, что оператор select возвращает только одну строку для каждого school_number=20201754 иначе вы закончите с ошибкой ORA-01422: exact fetch returns more than requested number of rowsи есть другие способы справиться с этим. (пока ничего не скажу по этому поводу)
  6. Заключительный момент, когда вы пытаетесь протестировать процедуру, например student_grade( v_lesson, v_midterm_1, v_midterm_2 , v_final, v_average ); -> вы передаете неправильное количество аргументов в процедуру, не включая v_school_no в качестве первого параметра.

Однако я создал свою собственную настройку и соответственно изменил процедуру и тест, см. Ниже.

--table definition
create table lessons (school_number number,lesson varchar2(100),midterm_notu_1 number,midterm_notu_2 number,final_notu number);
--inserting unique rows per school_number
insert into lessons values(20201754,'Maths',35,55,85);
insert into lessons values(20201755,'Science',45,65,95);

-- to enable the dbms_output
SET SERVEROUTPUT ON;

--procedure definition
CREATE OR REPLACE PROCEDURE student_grade(
        p_school_no IN lessons.school_number%type,
        p_lesson OUT lessons.lesson%type,
        p_midterm_1 OUT lessons.midterm_notu_1%type,
        p_midterm_2  OUT lessons.midterm_notu_2%type,
        p_final OUT lessons.final_notu%type,
        p_average OUT NUMBER
    )
IS
BEGIN
    SELECT
    d.lesson,
    d.midterm_notu_1,
    d.midterm_notu_2,
    d.final_notu
    INTO
        p_lesson,
        p_midterm_1,
        p_midterm_2,
        p_final
    FROM lessons d
    WHERE d.school_number = p_school_no;
    p_average := (((p_midterm_1 * 25)/100) + ((p_midterm_2 * 30)/100) + ((p_final * 45)/100));
END student_grade;
/

--testing the procedure    
DECLARE
    v_school_no lessons.school_number%type := 20201754;
    v_lesson lessons.lesson%type;
    v_midterm_1 lessons.midterm_notu_1%type;
    v_midterm_2  lessons.midterm_notu_2%type;
    v_final lessons.final_notu%type;
    v_average NUMBER;
BEGIN
    student_grade(
        v_school_no,
        v_lesson,
        v_midterm_1,
        v_midterm_2  ,
        v_final,
        v_average );
    DBMS_OUTPUT.put_line ('Student Grade');
    DBMS_OUTPUT.put_line ('School Number: ' ||v_school_no);
    DBMS_OUTPUT.put_line ('Midterm 1: ' || v_midterm_1);
    DBMS_OUTPUT.put_line ('Midterm 2: ' || v_midterm_2  );
    DBMS_OUTPUT.put_line ('Final: ' || v_final);
    DBMS_OUTPUT.put_line ('Average: ' || v_average );
END;
/

"Accept" (принять приглашение p_school_no) - это директива sqlplus, а не инструкция pl/sql. PL/SQL полностью выполняется внутри базы данных и не имеет средств "приема" ввода от пользователя. Единственный способ "принять" значения времени выполнения - указать их в командной строке при вызове процедуры. Вот для чего нужны эти параметры IN.

exec student_grade('schoolname');

Кроме того, "set" (SET p_average:=) недопустим для SELECT. Он принадлежит UPDATE.

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