Как я могу устранить ошибку 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, как их эффективно использовать. Проверьте их тоже.
Возвращаясь к проблеме, которую я пробовал на своей машине, в скрипте есть много проблем, которые мне приходилось исправлять одно за другим, просматривая сообщения об ошибках. Пожалуйста, найдите пункты и окончательное решение, которые должны работать, иначе я закончу.
Проблемы: есть отличия в названиях столбцов в таблице от написанного вами кода
WHERE d.shool_number = p_school_no;
-> shool_number не существующий столбец, вероятно,d.school_number
v_lesson lessons.lesson_name%type;
-> фактический столбецlesson
и нетlesson_name
. Я могу сказать это из вашего пункта select в процедуреp_lesson OUT lessons.lesson_name%type,
-> то же, что и в пункте 2p_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
используйте их вместо них.- Кроме того, убедитесь, что оператор select возвращает только одну строку для каждого
school_number=20201754
иначе вы закончите с ошибкойORA-01422: exact fetch returns more than requested number of rows
и есть другие способы справиться с этим. (пока ничего не скажу по этому поводу) - Заключительный момент, когда вы пытаетесь протестировать процедуру, например
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.