Такие инструменты, как SQL Developer, PL / SQL Developer и т. Д., Будут выделять ошибки компиляции, или в командной строке SQL * Plus вы можете ввести
show errors
сразу после компиляции, или же
show errors procedure who
Или вы можете запросить таблицу user_errors
.Какой бы инструмент вы ни использовали, вы должны уметь работать с ошибками компиляции.
Начните с того, чтобы привести в порядок код, чтобы его было легче читать и выполнять, и в целом он выглядит более профессионально.Кроме того, хотя они на самом деле не вызывают каких-либо ошибок, вы должны действительно изменить эти типы char
и varchar
на стандартные varchar2
(в идеале все должно быть привязано как academic.first_name%type
и т. Д., Но по одному за раз).
Вот исправленная версия:
create or replace procedure who
( code subject.code%type ) -- CHAR is a disastrous datatype you should never need
is
fname varchar2(50); -- VARCHAR2 is the standard string type, VARCHAR is reserved
lname varchar2(50); -- Also PL/SQL requires terminating semicolons here
title varchar2(256);
cursor c1 is
select first_name
, last_name
, subject.name
from academic
join teaches
on staff# = lecturer
join subject
on teaches.code = subject.code
where year < 2016
and teaches.code = who.code -- "code" on its own is ambiguous
group by first_name, last_name, subject.name;
begin
open c1;
loop
fetch c1 into fname, lname, title; -- Added 'fetch into'
if c1%notfound then
exit;
end if;
dbms_output.put_line(fname || ' ' || lname); -- It's dbms_output, with a '_'
dbms_output.put_line(title);
end loop;
close c1;
end who;
Компилируется.Но вы все еще можете упростить это, используя Cursor FOR Loop вместо сложного, многословного способа:
create or replace procedure who
( code subject.code%type )
is
begin
for r in (
select first_name
, last_name
, subject.name as title
from academic
join teaches
on staff# = lecturer
join subject
on teaches.code = subject.code
where year < 2016
and teaches.code = who.code
group by first_name, last_name, subject.name
)
loop
dbms_output.put_line(r.first_name || ' ' || r.last_name);
dbms_output.put_line(r.title);
end loop;
end who;
Это неявно объявляет курсор и запись с именем r
с тремяполя, основанные на курсоре, и он обрабатывает открытие, выборку и закрытие для вас.
Я не знаю ваших таблиц, но я предполагаю, что они примерно такие:
create table subject
( code varchar2(20) primary key
, name varchar2(30) not null );
create table academic
( staff# integer primary key
, first_name varchar2(20) not null
, last_name varchar2(20) not null );
create table teaches
( lecturer references academic(staff#) not null
, code references subject not null
, year number(4,0) not null
, constraint teaches_pk primary key (lecturer, code, year) );
Если это так, я бы использовал псевдонимы таблиц в запросе, как показано ниже, чтобы избежать двусмысленности:
select a.first_name
, a.last_name
, s.name as title
from academic a
join teaches t
on t.lecturer = a.staff#
join subject s
on s.code = t.code
where t.year < 2016
and t.code = who.code
group by a.first_name, a.last_name, s.name