You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PL/SQL包中Cursor可获取记录但无法读取值的问题求助

问题描述

我有一个PL/SQL包,其中定义的游标单独执行时能正常获取符合条件的记录,但集成到包中后却无法读取对应值。减少游标的WHERE条件后功能恢复正常,但上级要求必须保留当前游标的结构,不能精简条件。

相关代码如下:

SET serveroutput ON;
CREATE OR REPLACE PACKAGE CUSTOM.FINPACK_WELDUMMY AS
PROCEDURE FINPROC_WELDUMMY(inp_str VARCHAR2,
                        out_retCode OUT NUMBER,
                        out_rec OUT VARCHAR2);
END FINPACK_WELDUMMY;
/
CREATE OR REPLACE PACKAGE BODY CUSTOM.FINPACK_WELDUMMY AS
-------------------------------------------------------------------
-- Declaring the variables to be used in the Procedure
-------------------------------------------------------------------
    outArr                      TBAADM.basp0099.ArrayType;
    v_bodDate                   DATE;
    v_bank_id                   TBAADM.GAM.BANK_ID%type;
    v_acid                      VARCHAR2(11 CHAR);
    v_lacid                     VARCHAR2(11 CHAR);
    v_cif_id                    VARCHAR2(50 CHAR);
    v_acct_cls_flg              VARCHAR2(1);
    v_schm_code                 VARCHAR2(20);
    v_address_id                NUMBER(38);
    v_count                     VARCHAR2(3 CHAR);
    v_advance_instl             NUMBER(20,4);
    v_agreement_no              VARCHAR2(200);
    v_amtfin                    NUMBER(20,4);
    v_tenure                    NUMBER(3);
    v_title                     NVARCHAR2(75);
    v_fname                     NVARCHAR2(120);
    v_mname                     NVARCHAR2(120);
    v_lname                     NVARCHAR2(150);
    v_address1                  NVARCHAR2(200 CHAR);
    v_address2                  NVARCHAR2(200 CHAR);
    v_address3                  NVARCHAR2(200 CHAR);
    v_address4                  VARCHAR2(80 CHAR);
    v_landmark                  VARCHAR2(100);
    v_city                      NVARCHAR2(200 CHAR);
    v_statedesc                 NVARCHAR2(200 CHAR);
    v_zipcode                   NVARCHAR2(100 CHAR);
    v_branchdesc                VARCHAR2(132 CHAR);
    v_instl_num                 NUMBER(3);
    v_due_date                  DATE;
    v_instl_amt                 NUMBER(20,4);
    v_dmd_amt                   NUMBER(20,2);
    v_dflt_principal_flow_id    VARCHAR2(100);
    v_acct_crncy_code           VARCHAR2(3 CHAR);
    v_princomp                  NUMBER(20,4);
    v_intcomp                   NUMBER(20,4);
    v_endbal                    NUMBER(20,2);
    v_repaymode                 CHAR(3);
    v_effrate                   VARCHAR2(100);
    v_promotionid               VARCHAR2(200);
    v_cust_segment_code         VARCHAR2(200);
    v_cust_service_code         VARCHAR2(200);
    v_product_pre_fix           VARCHAR2(200);
    v_dob                       VARCHAR2(200);
    v_product                   VARCHAR2(16 CHAR);
    v_vendor                    VARCHAR2(200);  
    v_pre_printed_stationary    VARCHAR2(200);
    v_file_attchment_name       VARCHAR2(200);
    v_psw                       VARCHAR2(200);  
    v_identifier                VARCHAR2(200);  
    v_identifier2               VARCHAR2(200);
    v_amort_printing            VARCHAR2(200);
    v_month                     VARCHAR2(200);
    v_premi1                    VARCHAR2(200);
    v_preemi2                   VARCHAR2(200);  
    v_disbursed_amount          VARCHAR2(200);
    v_awb_no                    VARCHAR2(200);
    v_email                     NVARCHAR2(75);
    v_area                      VARCHAR2(200);      
    v_sc_code                   VARCHAR2(200);
    v_mobile_no                 NVARCHAR2(37.5);
    v_sol_id                    VARCHAR2(8 CHAR);

-------------------------------------------------------------------
--Cursor declaration
--This cursor will fetch all the LOAN accounts.
-------------------------------------------------------------------

    CURSOR getCustDetail 
        (
            v_bodDate                   DATE,
            v_bank_id                   TBAADM.GAM.BANK_ID%TYPE
        ) IS
        SELECT  A.ACID, A.TRAN_DATE, B.SRL_NUM, B.INTEREST_AMOUNT, B.SHDL_BALANCE, C.DFLT_PRINCIPAL_FLOW_ID, D.SOL_ID, D.ACCT_CLS_FLG, D.SCHM_CODE, D.ACID, D.ACCT_CRNCY_CODE, D.CIF_ID
        FROM    TBAADM.LTD A, TBAADM.LSBT B, TBAADM.LSP C, TBAADM.GAM D
        WHERE   A.TRAN_DATE = TO_DATE(v_bodDate,'DD-MM-YYYY') - 1
        AND     D.ACID = A.ACID 
        AND     B.ACID = A.ACID     
        AND     A.FLOW_ID = C.DFLT_DISBMNT_FLOW_ID
        AND     D.SCHM_CODE = C.SCHM_CODE
        AND     A.BANK_ID = D.BANK_ID AND B.BANK_ID = D.BANK_ID
        AND     C.BANK_ID = D.BANK_ID
        AND     A.DEL_FLG = 'N' AND C.DEL_FLG = 'N'
        AND     D.DEL_FLG = 'N'
        AND     D.SCHM_TYPE = 'LAA'
        AND     A.ENTITY_CRE_FLG = 'Y'
        AND     D.ENTITY_CRE_FLG = 'Y';

-----------------------------------------------------------
------------------ Procedure Body 1------------------------
-----------------------------------------------------------
PROCEDURE FINPROC_WELDUMMY(inp_str IN VARCHAR2,
                            out_retCode OUT NUMBER,
                            out_rec OUT VARCHAR2) AS

  BEGIN
    -- Your existing code goes here
    out_rec := NULL;
    out_retCode := 0;

    TBAADM.basp0099.formInputArr (inp_str, OutArr);
    v_bodDate  := TO_DATE(OutArr(0),'DD-MM-YYYY');
    v_bank_id  := OutArr(1);
    
        IF(NOT getCustDetail%ISOPEN) THEN
      --{
          OPEN getCustDetail(v_bodDate,v_bank_id);
      --}
        END IF;  

    IF getCustDetail%ISOPEN THEN
      --{
      FETCH getCustDetail INTO v_lacid, v_due_date, v_count, v_intcomp, v_princomp, v_dflt_principal_flow_id, v_sol_id, v_acct_cls_flg, v_schm_code, v_acid, v_acct_crncy_code, v_cif_id;
      --}
    END IF;

    IF getCustDetail%NOTFOUND THEN
      --{
      CLOSE getCustDetail;
      out_retCode  := 1;
      DBMS_OUTPUT.PUT_LINE('out_retCode: ' || out_retCode);
      RETURN;
      --}
    END IF;
--------------------------------------------------------
    -- FECTHING ACCOUNT DETAILS AFTER CURSOR
--------------------------------------------------------
    BEGIN
            SELECT  SOL_DESC
            INTO    v_branchdesc
            FROM    TBAADM.SOL
            WHERE   SOL_ID = v_sol_id
            AND     DEL_FLG = 'N'
            AND     BANK_ID = v_bank_id;
            EXCEPTION
                WHEN NO_DATA_FOUND THEN
                v_branchdesc := NULL;
    END;
       
    BEGIN
        SELECT
            nvl(
                abs(INTEREST_RATE), 0
            )
        INTO 
            v_effrate
        FROM
            TBAADM.EIT
        WHERE
            ENTITY_ID = v_acid
            AND BANK_ID = v_bank_id
            AND ENTITY_TYPE = 'ACCNT';

        EXCEPTION
            WHEN NO_DATA_FOUND THEN
                v_effrate := NULL;
    END;
    
    BEGIN
            SELECT
                nvl(
                        SUM(DMD_AMT), 0
                    )
            INTO v_dmd_amt
            FROM
                    TBAADM.LDT
            WHERE
                ACID = v_acid
                AND BANK_ID = v_bank_id
                AND DMD_FLOW_ID = v_dflt_principal_flow_id;

            EXCEPTION
            WHEN NO_DATA_FOUND THEN
                    v_dmd_amt := NULL;
    END;       
            
    BEGIN
        SELECT  UPFRONT_INSTL_INT_AMT, DIS_AMT
        INTO    v_advance_instl, v_amtfin
        FROM    TBAADM.LAM
        WHERE   ACID = v_acid
        AND     DEL_FLG = 'N'
        AND     ENTITY_CRE_FLG = 'Y'
        AND     BANK_ID = v_bank_id;
        EXCEPTION
            WHEN NO_DATA_FOUND THEN
            v_advance_instl := NULL;
            v_amtfin := NULL;
    END;   

    BEGIN
    SELECT  NUM_OF_DMDS, FLOW_AMT, NUM_OF_FLOWS
    INTO    v_instl_num, v_instl_amt, v_tenure
    FROM    TBAADM.LRS
    WHERE   ACID = v_acid
    AND     DEL_FLG = 'N'
    AND     BANK_ID = v_bank_id
    AND     FLOW_ID = v_dflt_principal_flow_id
    AND     ENTITY_CRE_FLG = 'Y';
    EXCEPTION
        WHEN NO_DATA_FOUND THEN
        v_instl_num := NULL;
        v_instl_amt := NULL;
        v_tenure := NULL;
    END; 

    BEGIN
        SELECT A.SEGMENTATION_CLASS, A.SUBSEGMENT, B.SALUTATION, B.CUST_FIRST_NAME, B.CUST_MIDDLE_NAME, B.CUST_LAST_NAME, B.EMAIL, B.PHONE_CELL, B.CUST_DOB
        INTO v_cust_segment_code,v_cust_service_code, v_title, v_fname, v_mname, v_lname, v_email, v_mobile_no, v_dob
        FROM CRMUSER.PSYCHOGRAPHIC A,CRMUSER.ACCOUNTS B
        WHERE A.ACCOUNTID = B.ACCOUNTID
        AND A.BANK_ID = v_bank_id AND B.BANK_ID = v_bank_id
        AND A.ORGKEY = v_cif_id AND B.ORGKEY = v_cif_id;
        EXCEPTION
        WHEN NO_DATA_FOUND THEN
        v_cust_segment_code := 'NA';
        v_cust_service_code := 'NA';
        v_title := 'NA';
        v_fname := 'NA';
        v_mname := 'NA';
        v_lname := 'NA';
        v_email := 'NA';
        v_mobile_no := 'NA';
        v_dob := 'NA';
    END;       
    
    BEGIN
        SELECT ADDRESS_LINE1,ADDRESS_LINE2, ADDRESS_LINE3, CITY, STATE, ZIP
        INTO v_address1, v_address2, v_address3, v_city, v_statedesc, v_zipcode
        FROM CRMUSER.ADDRESS
        WHERE ACCOUNTID = v_acid
        AND BANK_ID = v_bank_id;
        EXCEPTION
        WHEN NO_DATA_FOUND THEN
        v_address1 := 'NA';
        v_address2 := 'NA';
        v_address3 := 'NA';
        v_city := 'NA';
        v_statedesc := NULL;
        v_zipcode := NULL;
    END;

    BEGIN
        v_address4                  := NULL;
        v_landmark                  := NULL;
        v_vendor                    := NULL;
        v_pre_printed_stationary    := NULL;
        v_file_attchment_name       := NULL;
        v_psw                       := NULL;
        v_identifier                := NULL;
        v_month                     := NULL;
        v_amort_printing            := 'Y'; 
        v_premi1                    := 'NA';
        v_preemi2                   :='NA';
        v_disbursed_amount          :='NA';
        v_awb_no                    :='NA';
        v_area                      :='NA';
        v_sc_code                   :='NA';
    END;

    out_rec := v_count || '|' || v_advance_instl || '|' || v_agreement_no || '|' || v_amtfin || '|' || v_tenure || '|' || v_title || '|' || v_fname || '|' || v_mname || '|' || v_lname || '|' || v_address1 || '|' || v_address2 || '|' || v_address3 || '|' || v_address4 || '|' || v_landmark || '|' || v_city || '|' || v_statedesc || '|' || v_zipcode || '|' || v_branchdesc || '|' || v_instl_num || '|' || v_due_date || '|' || v_instl_amt || '|' || v_dmd_amt || '|' || v_dflt_principal_flow_id || '|' || v_princomp || '|' || v_intcomp || '|' || v_endbal || '|' || v_repaymode || '|' || v_effrate || '|' || v_promotionid || '|' || v_cust_segment_code || '|' || v_cust_service_code || '|' || v_product_pre_fix || '|' || v_dob || '|' || v_product|| '|' || v_vendor || '|' || v_pre_printed_stationary || '|' || v_file_attchment_name || '|' || v_psw || '|' || v_identifier || '|' || v_identifier2 || '|' || v_amort_printing || '|' || v_month || '|' || v_premi1 || '|' || v_preemi2 || '|' || v_disbursed_amount || '|' || v_awb_no || '|' || v_email
    || '|' || v_area || '|' || v_sc_code || '|' || v_mobile_no || '|' || v_sol_id;


END FINPROC_WELDUMMY;


END FINPACK_WELDUMMY;
/
-------------------------------------------------------
-- Execution grants are given to Tbacust Tbautil Tbagen
-------------------------------------------------------
/
DROP SYNONYM CUSTOM.C_FINPACK_WELDUMMY;
/
CREATE SYNONYM CUSTOM.C_FINPACK_WELDUMMY FOR CUSTOM.FINPACK_WELDUMMY;
/
GRANT EXECUTE ON CUSTOM.FINPACK_WELDUMMY TO TBAGEN,TBAUTIL,TBAADM;
/
SHOW ERRORS;

排查及修复方案

1. 修复游标日期转换错误

游标参数v_bodDate本身是DATE类型,无需再用TO_DATE转换,这会导致隐式转换逻辑错误,直接修改WHERE条件:

-- 原条件
A.TRAN_DATE = TO_DATE(v_bodDate,'DD-MM-YYYY') - 1
-- 修改后
A.TRAN_DATE = v_bodDate - 1

2. 修正游标打开逻辑的隐患

当前代码仅在游标未打开时才打开,若过程被重复调用,游标可能处于打开状态导致读取异常。建议改用更安全的FOR循环遍历游标(自动处理打开/关闭):

-- 替换原打开、FETCH逻辑
FOR rec IN getCustDetail(v_bodDate, v_bank_id) LOOP
  v_lacid := rec.ACID;
  v_due_date := rec.TRAN_DATE;
  v_count := TO_CHAR(rec.SRL_NUM); -- 类型匹配转换
  v_intcomp := rec.INTEREST_AMOUNT;
  v_princomp := rec.SHDL_BALANCE;
  v_dflt_principal_flow_id := rec.DFLT_PRINCIPAL_FLOW_ID;
  v_sol_id := rec.SOL_ID;
  v_acct_cls_flg := rec.ACCT_CLS_FLG;
  v_schm_code := rec.SCHM_CODE;
  v_acid := rec.ACID;
  v_acct_crncy_code := rec.ACCT_CRNCY_CODE;
  v_cif_id := rec.CIF_ID;
  EXIT; -- 仅取第一条记录时添加
END LOOP;

3. 验证变量类型匹配

游标中B.SRL_NUM是数字类型,但v_count定义为VARCHAR2(3 CHAR),隐式转换可能导致赋值失败。修改v_count为NUMBER类型,或在游标中显式转换:

-- 游标SELECT中修改
B.SRL_NUM AS SRL_NUM -> TO_CHAR(B.SRL_NUM) AS SRL_NUM

4. 验证参数传递正确性

在过程中添加调试输出,确认传入的v_bodDate和v_bank_id值符合预期:

DBMS_OUTPUT.PUT_LINE('v_bodDate: ' || TO_CHAR(v_bodDate, 'DD-MM
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 00:17:12