在调用子程序时,必须事先在独立程序内块层次结构的某个位置声明它,但该位置必须在调用它的位置前面。换句话说,当从头到尾扫描SPL代码时,必须在调用之前找到子程序声明。

但是,有一种构造SPL代码的方式,可使子程序的完整声明(即,可选声明部分、必需可执行部分和可选异常部分)出现在调用它的代码点之后的SPL代码中。

这通过在调用之前在SPL代码中插入前置声明来完成。前置声明是子存储过程或子函数名称、形参和子函数的规格;如果是子函数,则返回类型。

完整子程序规格(由可选声明部分、可执行部分和可选异常部分组成)必须与前置声明在同一声明部分中指定,但可出现在用前置声明调用此子程序的其他子程序声明之后。

前置声明的典型用法是两个子程序相互调用,如下所示:

DECLARE
    FUNCTION add_one (
        p_add       IN NUMBER
    ) RETURN NUMBER;
    FUNCTION test_max (
        p_test      IN NUMBER)
    RETURN NUMBER
    IS
    BEGIN
        IF p_test < 5 THEN
            RETURN add_one(p_test);
        END IF;
        DBMS_OUTPUT.PUT('Final value is ');
        RETURN p_test;
    END;
    FUNCTION add_one (
        p_add       IN NUMBER)
    RETURN NUMBER
    IS
    BEGIN
        DBMS_OUTPUT.PUT_LINE('Increase by 1');
        RETURN test_max(p_add + 1);
    END;
BEGIN
    DBMS_OUTPUT.PUT_LINE(test_max(3));
END;

子函数 test_max 调用子函数 add_one(后者也调用子函数 test_max),因此某一子程序需要前置声明,这是为匿名块声明部分开头的 add_one 实现的。

匿名块所生成的输出如下所示:

Increase by 1
Increase by 1
Final value is 5