如何调用在另一个过程中声明的过程?

How can I call a procedure declared inside another procedure?

我对 Db2 中的过程有疑问。我使用 "CREATE PROCEDURE" 创建了一个存储过程,在其中我有另一个使用 "DECLARE PROCEDURE" 声明的存储过程。但是,这个由 declare 创建的过程不能使用 "CALL".

调用

当我尝试 运行 程序时,Db2 returns:

[Code: -440, SQL State: 42884] DB2 SQL Error: SQLCODE=-440, SQLSTATE=42884, SQLERRMC=DMTLDBR.SP_DASH_CALENDARIO.PROCURA_DIA_UTIL_POST_DIA1;PROCEDURE, DRIVER=4.25.1301

如何调用声明的过程? (PROCURA_DIA_UTIL_POST_DIA1)

代码:

create or replace PROCEDURE           "SP_DASH_CALENDARIO" (IN P_MES INTEGER)
BEGIN

------
DECLARE SQLSTATE                       CHAR(5) DEFAULT ' ';

DECLARE V_ANO_MES                      DECIMAL(6); 
DECLARE V_ID_DIA                       ANCHOR DATA TYPE TO DMTLDBR.TB_DIM_DIADIA.ID_DIA;

DECLARE V_VAL_REAL_CAL                 ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_TONLIQUIDO;
DECLARE V_VAL_TONVNEMA                 ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_TONVNEMA;
DECLARE V_VAL_FAT357_CAL               ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_FAT357; 
DECLARE V_VAL_PERDA_FAT_CAL            ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_PERDA;

DECLARE V_SUM_VAL_REAL_CAL             ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_REAL_CAL;
DECLARE V_SUM_VAL_TONVNE_CAL           ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_TONVNE_CAL;
DECLARE V_SUM_VAL_TONLIQUIDO_ZBCL_CAL  ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_TONLIQUIDO_ZBCL_CAL;
DECLARE V_SUM_VAL_TONLIQUIDO_CAL       ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_TONLIQUIDO_CAL;
DECLARE V_SUM_VAL_FAT357_CAL           ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_FAT357_CAL;   

DECLARE V_VAL_TONLIQUIDO_CAL           ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_TONLIQUIDO_CAL;
DECLARE V_VAL_TONVNE_CAL               ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_TONVNE_CAL;
DECLARE V_VAL_TONLIQUIDO_ZBCL_CAL      ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_TONLIQUIDO_ZBCL_CAL; 

DECLARE V_VAL_PLANO_FAT_CAL            ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_PLANEJ_MAN.VAL_PLANO; 
DECLARE V_VAL_PLANO                    ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_PLANEJ_MAN.VAL_PLANO; 
DECLARE V_TOTAL_PLANO_DESOVA_SEMANAL   ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_PLANEJ_MAN.TOTAL_PLANO_DESOVA_SEMANAL;

DECLARE V_ID_DIASEMANA                 ANCHOR DATA TYPE TO DMTLDBR.TB_DIM_DIADIA.ID_DIASEMANA;
DECLARE V_FLG_HOLIDAY                  ANCHOR DATA TYPE TO DMTLDBR.TB_DIM_DIADIA.FLG_HOLIDAY;

DECLARE V_IND_LEGENDA                  DECIMAL(1);
DECLARE V_VARIANTE                     ANCHOR DATA TYPE TO DMTLDBR.TB_DIM_PRODVARIANTE.ID_VARIANTE;

DECLARE V_VAL_PERDA                    ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_TONLIQUIDO;
DECLARE V_VAL_DESOVA                   ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_TONLIQUIDO;
DECLARE V_VAL_UHT                      ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_TONLIQUIDO;
DECLARE V_VAL_SUCO                     ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_TONLIQUIDO;
DECLARE V_VAL_REQ                      ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_TONLIQUIDO;
DECLARE V_FAT_UHT                      ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_FAT357;  
DECLARE V_FAT_REQ                      ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_FAT357; 


DECLARE V_ID_DIA_INI                   ANCHOR DATA TYPE TO DMTLDBR.TB_DIM_DIADIA.ID_DIA;
DECLARE V_ID_DIA_FIM                   ANCHOR DATA TYPE TO DMTLDBR.TB_DIM_DIADIA.ID_DIA;
DECLARE FLAG_DIA_UTIL                  BOOLEAN;
DECLARE V_SUM_VAL_TONVNEMA_CAL         ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_TONVNEMA_CAL;
DECLARE V_SUM_VAL_FAT357               ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_FAT357;
DECLARE V_SUM_VAL_ABATIMENTOREPORTADO  ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_ABATIMENTOREPORTADO;
DECLARE V_SUM_VAL_ICMSZFMREPORTADO     ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_ICMSZFMREPORTADO;

DECLARE V_PROC                         ANCHOR DATA TYPE TO DMTLDBR.TB_TMP_LOG_EXECUTION_PROC.SYNCPOINT_PROC;
SET V_PROC = 'SP_DASH_CALENDARIO';

-- =========================================================================================================
--   P R O C   P R O C U R A _ D I A _ U T I L _ P O S T _ D I A 1
--
--  OBTEM O PRIMEIRO DIA ÚTIL DO MÊS (QUE NÃO SEJA DOMINGO NEM FERIADO)
--
-- =========================================================================================================
BEGIN
DECLARE PROCEDURE PROCURA_DIA_UTIL_POST_DIA1(IN P_ID_MES INTEGER)
BEGIN

        DECLARE V_ACHOU  DECIMAL(1) DEFAULT 0;
        DECLARE CONTINUE HANDLER FOR SQLEXCEPTION, SQLWARNING, NOT FOUND BEGIN END;

        SET V_ID_DIA = NULL;

        L1: LOOP -- (LP01)

        BEGIN  -- (BE02.)

                DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' BEGIN END;

                SELECT MIN(ID_DIA) INTO V_ID_DIA
                FROM   DMTLDBR.TB_DIM_DIADIA
                WHERE  ID_MES     = P_ID_MES
                AND    ID_DIASEMANA  <> 1  -- DOMINGO
                AND    FLG_HOLIDAY = 0;

        END; -- (BE02.)

        IF SQLSTATE = '00000' THEN
                LEAVE L1;
         --SET V_ACHOU = 1;
        END IF;

        END LOOP L1; -- (LP01.)

END;
END;

CALL DMTLDBR.PROCURA_DIA_UTIL_POST_DIA1(201909);

END

问题中显示的代码中存在不止一个错误。

您正在使用 本地过程,这是在另一个过程中声明的过程的名称。

本地程序在正确使用时工作正常。

编译成功的一些建议:

  • declare procedure 必须出现在调用过程中任何可执行语句或新块之前。

    移动语句 SET V_PROC = 'SP_DASH_CALENDARIO' 使其出现 在调用本地过程之前(或主过程块内的任何地方 AFTER 所有声明(包括声明本地过程之后)。

    此外,删除 DECLARE PROCEDURE 之前行中的 BEGIN(和匹配的 END)。 您希望 all 声明出现在 any 可执行语句或新的 begin-end 块之前。

  • 本地过程名称必须是非限定的 both DECLARE and CALL 但是您在 CALL 语句中使用了限定符,这将阻止 Db2 找到本地过程。

您程序的最后一部分将如下所示:

...snip...

DECLARE V_SUM_VAL_ICMSZFMREPORTADO     ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_ICMSZFMREPORTADO;
DECLARE V_PROC                         ANCHOR DATA TYPE TO DMTLDBR.TB_TMP_LOG_EXECUTION_PROC.SYNCPOINT_PROC;


    -- =========================================================================================================
    --   P R O C   P R O C U R A _ D I A _ U T I L _ P O S T _ D I A 1
    --
    --  OBTEM O PRIMEIRO DIA ÚTIL DO MÊS (QUE NÃO SEJA DOMINGO NEM FERIADO)
    --
    -- =========================================================================================================
    DECLARE PROCEDURE PROCURA_DIA_UTIL_POST_DIA1(IN P_ID_MES INTEGER)
    BEGIN

            DECLARE V_ACHOU  DECIMAL(1) DEFAULT 0;
            DECLARE CONTINUE HANDLER FOR SQLEXCEPTION, SQLWARNING, NOT FOUND BEGIN END;

            SET V_ID_DIA = NULL;

            L1: LOOP -- (LP01)

            BEGIN  -- (BE02.)

                    DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' BEGIN END;

                    SELECT MIN(ID_DIA) INTO V_ID_DIA
                    FROM   DMTLDBR.TB_DIM_DIADIA
                    WHERE  ID_MES     = P_ID_MES
                    AND    ID_DIASEMANA  <> 1  -- DOMINGO
                    AND    FLG_HOLIDAY = 0;

            END; -- (BE02.)

            IF SQLSTATE = '00000' THEN
                    LEAVE L1;
             --SET V_ACHOU = 1;
            END IF;

            END LOOP L1; -- (LP01.)

    END;

    SET V_PROC = 'SP_DASH_CALENDARIO';

    CALL PROCURA_DIA_UTIL_POST_DIA1(201909);

    END@

A Compound SQL (compiled) statement 要求内部声明/语句的顺序严格。
例如:

--#SET TERMINATOR @
CREATE OR REPLACE PROCEDURE TEST_LOCAL(P_I INT)
BEGIN
    -- SQL-variable-declarations
    DECLARE L_I INT;

    -- DECLARE-CURSOR-statements
    DECLARE C1 CURSOR FOR VALUES 1;

    -- procedure-declaration
    DECLARE PROCEDURE TEST_LOCAL_NESTED(P_J INT) BEGIN END;

    -- handler-declarations
    DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN END;

    -- SQL-procedure-statements
    CALL TEST_LOCAL_NESTED(P_I);
END@

每个 BEGIN END 块的简要说明:

1-st: 全部 SQL-variable-declarations
第二:所有 DECLARE-CURSOR-statements
第三名:全部 procedure-declaration
第 4 位:所有 handler-declarations

全部SQL-procedure-statements仅次于此。这些语句可能包含嵌套的 BEGIN END 块,其中适用相同的严格声明/语句规则。