2016-03-29 3 views
0

У меня проблема с процедурами в PL/SQL. У меня есть общедоступная процедура, объявленная в пакете, и я хочу вызвать другую процедуру (закрытую) внутри первой.Взаимодействие между сборником и таблицей

PROCEDURE show_notesforstudent (number_id IN number) as 
    ... 
    DBMS_OUTPUT.PUT_LINE('The notes for the student with number_id X are: '|| Y); 

    DBMS_OUTPUT.PUT_LINE('here is the call for the private procedure'); 
    erase_student(number_id); 
END; 

Этот код является общим примером, мой код больше, и я не могу все это перечислить. Вот только основная идея. Для этого вызова я сталкиваюсь с этой ошибкой: «Ошибка (31,5): PLS-00313:« erase_student »не объявлен в этой области».

Реализация процедуры erase_student является:

PROCEDURE erase_student(n_id students.number_id%type) AS 
    student_inexistent EXCEPTION; 
    PRAGMA EXCEPTION_INIT(student_inexistent, -20002); 
    counter integer; 
BEGIN 
    SELECT COUNT(nmber_id) INTO counter FROM studens where number_id = n_id; 
    IF counter = 0 THEN 
     raise student_inexistent; 
    END IF; 
    DELETE FROM students WHERE number_id = n_id; 
    EXCEPTION 
    WHEN student_inexistent THEN 
     raise_application_error (-20002, 'Student with number_id' || n_id ||  '  doesn't exists in database'); 
END stergere_student;` 
+1

Объявите 'процедуру erase_student' перед' show_notesforstudent' или использовать вышеописанную декларацию заголовка 'erase_student' в в начале процедуры. – MT0

+0

Возможно, 'erase_student' не существует из-за синтаксических ошибок в' erase_students'. Похоже, что имя таблицы в 'SELECT COUNT (*) ...' должно быть «учениками», а не «учениками». Кроме того, имя процедуры ('erase_student') не совпадает с именем в инструкции' END stergere_student'. Возможно, проблема при переводе (с румынского?). Кроме того, в вызове 'RAISE_APPLICATION_ERROR' апостроф в' doesn't' должен быть удвоен ('doesn''t'), поэтому вы получаете один апостроф в строковом литерале. Удачи. –

+0

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

ответ

1

Позволяет упростить код и сделать его синтаксически правильно:

CREATE OR REPLACE PACKAGE package_name 
AS 
    PROCEDURE show_notesforstudent (number_id IN number); 
END; 
/

CREATE OR REPLACE PACKAGE BODY package_name 
AS 
    PROCEDURE show_notesforstudent (number_id IN number) 
    AS 
    BEGIN 
     erase_student(number_id); 
    END; 

    PROCEDURE erase_student(n_id NUMBER) AS BEGIN NULL; END; 
END; 
/

Тем не менее, до сих пор не компилируется, как мы получим PLS-00313: 'ERASE_STUDENT' not declared in this scope. Он может быть исправлен путем реорганизации пакета для обеспечения того, чтобы частная процедура была объявлена ​​до ее вызова; как это:

CREATE OR REPLACE PACKAGE BODY package_name 
AS 
    PROCEDURE erase_student(n_id NUMBER) AS BEGIN NULL; END; -- Header and body 

    PROCEDURE show_notesforstudent (number_id IN number) 
    AS 
    BEGIN 
     erase_student(number_id); 
    END; 
END; 
/

Однако, если вы хотите сохранить порядок процедур в пакете, то вы могли бы просто использовать опережающее объявление, чтобы объявить заголовок для частной процедуры, прежде чем он называется и объявить тело впоследствии ; как это:

CREATE OR REPLACE PACKAGE BODY package_name 
AS 
    PROCEDURE erase_student(n_id NUMBER); -- Header only 

    PROCEDURE show_notesforstudent (number_id IN number) 
    AS 
    BEGIN 
     erase_student(number_id); 
    END; 

    PROCEDURE erase_student(n_id NUMBER) AS BEGIN NULL; END; -- Header and body 
END; 
/