Есть ли лучший способ написать процедуру AVG? - PullRequest
0 голосов
/ 05 апреля 2020

Я написал эту процедуру, но она продолжает показывать «ПРЕДУПРЕЖДЕНИЕ: процедура создается с ошибками компиляции», и я не знаю почему, вот таблица, которую я создал

create table EnrolledInClasses (
    St_Id char(9) primary key, 
    C_Id char(6),
    GradeN Number(2),
    constraint FK_StId Foreign key (St_Id) references Student (St_Id),
    constraint FK_CoID Foreign key (C_Id) references course (C_Id)
    constraint CheckGrade check (Grade>-1)
);

, а вот процедура:

CREATE OR REPLACE PROCEDURE Avg_grades
IS
avg_grades NUMBER := 0;

BEGIN
SELECT AVG (Grade)
INTO avg_grades
FROM EnrolledInClasses
dbms_output.put_line('The average of grades is :'||avg_grades);
EXCEPTION
WHEN NO_DATA_FOUND
  THEN
  DBMS_OUTPUT.put_line ('No Data Is Found..');
  END;
  /

1 Ответ

4 голосов
/ 05 апреля 2020

Поскольку вы используете PL / SQL Developer , убедитесь, что вы пишете свой код в окне процедуры. Тогда ошибка компиляции будет четко выделена. В данном случае это пропущенная точка с запятой в конце оператора select into.

[

Или в SQL* Plus вы можете использовать show errors:

Warning: Procedure created with compilation errors.

SQL> show errors
Errors for PROCEDURE AVG_GRADES:

LINE/COL ERROR
-------- -----------------------------------------------------------------
6/1      PL/SQL: SQL Statement ignored
9/12     PL/SQL: ORA-00933: SQL command not properly ended

или полный синтаксис , show errors procedure avg_grades.

Или вы можете напрямую запросить dba|all|cdb|user_errors:

select * from user_errors e
where  e.name = 'AVG_GRADES'
and    e.attribute = 'ERROR';

Кроме того, определение таблицы можно записать более кратко:

create table enrolledinclasses
( st_id   primary key  constraint fk_stid references student(st_id)
, c_id    constraint   fk_coid references course (c_id)
, grade   number(2)    constraint checkgrade check (grade>-1)
);

student.st_id и course.c_id, вероятно, должны быть числами или целыми числами или, по крайней мере, varchar2, а не char .

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

create or replace procedure avg_grades as
    avg_grades number := 0;
begin
    select avg(grade) into avg_grades
    from   enrolledinclasses;

    dbms_output.put_line('The average grade is: ' || avg_grades);
exception
    when no_data_found then
        dbms_output.put_line('No Data Is Found.');
end;

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

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

...