Вы не можете (вперед) объявлять функцию в теле, потому что она уже была объявлена в спецификации.
Это просто проверить с очень незначительным заполнением вашего псевдокода:
CREATE OR REPLACE PACKAGE pckg_test IS
FUNCTION fun_test(ID NUMBER) RETURN NUMBER;
PROCEDURE proc_test (id number);
END pckg_test ;
/
Package PCKG_TEST compiled
CREATE OR REPLACE PACKAGE BODY pckg_test IS
FUNCTION fun_test(ID NUMBER) RETURN NUMBER; --fwd declaration
PROCEDURE proc_test (id number) is
x number;
BEGIN
x := fun_test(1);
END;
FUNCTION fun_test(ID NUMBER) RETURN NUMBER is
BEGIN
return 42;
END;
END pckg_test;
/
Package Body PCKG_TEST compiled
LINE/COL ERROR
--------- -------------------------------------------------------------
2/1 PLS-00305: previous use of 'FUN_TEST' (at line 2) conflicts with this use
2/1 PL/SQL: Item ignored
2/10 PLS-00328: A subprogram body must be defined for the forward declaration of FUN_TEST.
Errors: check compiler log
PLS-00305 из-за вашей предварительной декларации, такой же (имя и типы данных), что и в спецификации пакета.
PLS-00328 немного вводит в заблуждение;полное объявление fun_test
, похоже, связано с общедоступной спецификацией, а предварительное объявление - даже если оно само выдает ошибку - не имеет полного полного объявления.
Если вы просто удалите или прокомментируетеиз предварительного объявления, то оно успешно компилируется:
CREATE OR REPLACE PACKAGE BODY pckg_test IS
--FUNCTION fun_test(ID NUMBER) RETURN NUMBER; --fwd declaration
PROCEDURE proc_test (id number) is
x number;
BEGIN
x := fun_test(1);
END;
FUNCTION fun_test(ID NUMBER) RETURN NUMBER is
BEGIN
return 42;
END;
END pckg_test;
/
Package Body PCKG_TEST compiled
Вам не требуется (и не допускается) предварительное объявление fun_test
в теле пакета, потому что оно открыто объявлено в спецификации пакета -эта общедоступная спецификация делает функцию доступной во всем теле пакета.Таким образом, proc_test
все еще может вызывать fun_test
, хотя он стоит первым в коде тела.Публичная спецификация имеет тот же эффект, что и предварительное объявление.
, значит, я могу дать объявление fwd только для частных подпрограмм?
Да.