" PL / SQL:函数返回没有值"已完成对PL / SQL函数的调用,但未执行任何RETURN语句

时间:2016-01-18 12:44:33

标签: sql oracle plsql

我已经创建了一个带有函数的PL / SQL包,但是当通过传递输入值调用包时,我得到以下消息:

ORA-06503: PL/SQL: Function returned without value ORA-06512: at "APPDATA.PWH_RELEASE_PAYMENT_ORDER_PKG", line 107 ORA-06512: at "APPDATA.PWH_RELEASE_PAYMENT_ORDER_PKG", line 158 ORA-06512: at line 36 06503. 00000 - "PL/SQL: Function returned without value" *Cause: A call to PL/SQL function completed, but no RETURN statement was executed.*Action: Rewrite PL/SQL function, making sure that it always returns a value of a proper type. /* Type Bank ID Collection */ CREATE OR REPLACE TYPE TYPE_BANKID_COLL FORCE AS TABLE OF VARCHAR2(35 CHAR); -- Type BankId Collection / /* Type processing line collection */ create or replace TYPE TYPE_PROCESSINGLINE_COLL FORCE AS TABLE OF VARCHAR2(50 CHAR); / /* Type processing line ID collection */ CREATE OR REPLACE TYPE TYPE_PROCESSINGLINEID_COLL FORCE AS TABLE OF NUMBER; / /* Type Processing line flows - Object type 1 */ CREATE OR REPLACE TYPE TYPE_PROCESSINGLINEFLOWS FORCE AS OBJECT ( processinglineid NUMBER, processinglineflow TYPE_PROCESSINGLINEFLOW ); / -- 2 data types /* Type Processing line flows coll - Nested table of Object type 1 */ CREATE OR REPLACE TYPE TYPE_PROCESSINGLINEFLOWS_COLL FORCE AS TABLE OF TYPE_PROCESSINGLINEFLOWS; / -- Type Processing line flows Collection /* Type Processing line payment - Object type 2 */ create or replace TYPE TYPE_PROCESSINGLINEPAYMENT FORCE AS OBJECT ( processingline VARCHAR2(50 CHAR), processingLineFlows TYPE_PROCESSINGLINEFLOW_COLL, messages TYPE_MESSAGE_COLL, reservationRefs TYPE_RSVDTLS_COLL ); / /* Type Processing line payment Collection - Nested table of Object type 2 */ CREATE OR REPLACE TYPE TYPE_PROCESSINGLINEPAYMT_COLL FORCE AS TABLE OF TYPE_PROCESSINGLINEPAYMENT; / /* Type Bank due payment - Object type 3 */ CREATE OR REPLACE TYPE TYPE_BANKDUEDATEPAYMENT FORCE AS OBJECT ( bankid VARCHAR2(35 CHAR), payments TYPE_PROCESSINGLINEPAYMT_COLL ) / /* Type Bank due date payment Collection - Nested table of Object type 3 */ CREATE OR REPLACE TYPE TYPE_BANKDUEDATEPAYMENT_COLL FORCE AS TABLE OF TYPE_BANKDUEDATEPAYMENT; / /* Type POR Due date process */ CREATE OR REPLACE TYPE TYPE_PORDUEDATEPROCESS FORCE AS OBJECT ( duedateid NUMBER, payments TYPE_BANKDUEDATEPAYMENT_COLL ); /


此处正在运行包裹调用:

/* Start of package header - pwh release payment order pkg */
create or replace PACKAGE pwh_release_payment_order_pkg AS
      /* 
        ======================================================================================
        Constants
        ======================================================================================
      */
        c_readyForReservationEngine         CONSTANT CHAR(4) := 'RFRE';         -- ready for reservation engine
        c_readyForPaymentEngine             CONSTANT CHAR(4) := 'RFPE';         -- ready for payment engine

      -- releaseProcessOrder
        FUNCTION releaseProcessOrder (
            p_processinglines TYPE_PROCESSINGLINE_COLL,                             -- p_processinglines : TYPE_PROCESSINGLINES
            /*
                create or replace TYPE TYPE_PROCESSINGLINE_COLL FORCE AS TABLE OF VARCHAR2(50 CHAR);    
            */
            p_portype         VARCHAR2,                                             -- Type BankID Collection                                               
            p_banksinprocess  TYPE_BANKID_COLL,                                     -- Banks in process
            /*
                From the types file:
                CREATE OR REPLACE TYPE TYPE_BANKID_COLL
                FORCE AS TABLE OF VARCHAR2(35 CHAR);                
            */
            p_releasedate       paymentinfo.releasedate%type,                           -- Release Date
            p_paymentstatuses   TYPE_PAYMENT_STATUS_COLL,                               -- Payment Statuses
            p_processingdate    duedateprocess.processingdate%type                      -- Type release payment order  
        ) RETURN TYPE_PORDUEDATEPROCESS;  


/*  End of the package header */  
END pwh_release_payment_order_pkg;                                          
/
/* End of package header - End of pwh release payment order pkg */

/* Start of package body */
create or replace PACKAGE BODY pwh_release_payment_order_pkg
AS
        FUNCTION getRsvDtlsForTransactions(                                         /*  get Reservation Details For Transactions  */
            p_transactionIds TYPE_TRANSACTIONID_COLL 
            ) RETURN TYPE_RSVDTLS_COLL                                                  /*  Type reservation details collection  */                         
        IS
            v_reservationDetails TYPE_RSVDTLS_COLL := TYPE_RSVDTLS_COLL();          /*  v_reservationDetails  */
            BEGIN
                SELECT TYPE_RSVDTLS( reservationreference, reservationtime, reservedamount, currencycode, fk_transactionsid ) BULK COLLECT
                /*  


                */
                INTO v_reservationDetails
                FROM reservation_details rsvd           
                INNER JOIN TABLE(p_transactionIds) tids                             /*  p_transactionIds - tids  */
                ON rsvd.fk_transactionsid = tids.COLUMN_VALUE;                      
                RETURN v_reservationDetails;                                            /*  return v_reservationdetails */
            END;

        FUNCTION getProcessingLineFlows(                                        
            p_processingLineIds IN TYPE_PROCESSINGLINEID_COLL,              
            v_status OUT VARCHAR2
        )RETURN TYPE_PROCESSINGLINEFLOWS_COLL
        AS
            v_processinglineflows TYPE_PROCESSINGLINEFLOWS_COLL := TYPE_PROCESSINGLINEFLOWS_COLL(); 
            v_cnt NUMBER;  
            v_processingLineIds TYPE_PROCESSINGLINEID_COLL := TYPE_PROCESSINGLINEID_COLL();             
            BEGIN
                SELECT TYPE_PROCESSINGLINEFLOWS(fk_processinglineid, TYPE_PROCESSINGLINEFLOW( FUNCTION, component )) BULK COLLECT
                INTO v_processingLineFlows
                FROM processinglineflow flow                                                
                INNER JOIN TABLE (p_processingLineIds) p
                ON flow.fk_processinglineid = p.COLUMN_VALUE;

                SELECT COUNT(flw.processinglineflow.function)                               
                INTO v_cnt
                FROM TABLE (v_processinglineflows) flw                                  
                WHERE flw.processinglineflow.function = 'FUND_CHECK';                       

                IF v_cnt                              = p_processingLineIds.count THEN  
                SELECT COUNT(DISTINCT flw.processinglineflow.component)                     
                INTO v_cnt
                FROM TABLE (v_processinglineflows) flw
                WHERE flw.processinglineflow.function = 'FUND_CHECK';                   

                IF v_cnt                              = 1 THEN                              
                    v_status                           := c_readyForReservationEngine;  
                    RETURN v_processingLineFlows;                                                                           
                END IF;
                ELSIF v_cnt = 0 THEN                                                        
                    SELECT COUNT(flw.processinglineflow.function)                           
                    INTO v_cnt                                                                                                                          
                    FROM TABLE (v_processinglineflows) flw                                  
                    WHERE flw.processinglineflow.function = 'PE_SELECTION';         

                    IF v_cnt                              = 1 THEN                                                      
                        v_status                           := c_readyForPaymentEngine;      
                        RETURN v_processingLineFlows;
                    END IF;
                    ELSE
                        raise_application_error (-20301, 'Invalid processing lines');           
                    END IF;
            END;



        FUNCTION releaseProcessOrder(
            p_processinglines   TYPE_PROCESSINGLINE_COLL,                                                           
            p_portype           VARCHAR2,                                                                           
            p_banksinprocess    TYPE_BANKID_COLL,                                                                   
            p_releasedate       paymentinfo.releasedate%type,                                                       
            p_paymentstatuses   TYPE_PAYMENT_STATUS_COLL,                                                           
            p_processingdate    duedateprocess.processingdate%type 
            )RETURN TYPE_PORDUEDATEPROCESS                                                                              
            AS
                v_status              VARCHAR2(4 CHAR);                                                                 
                v_functionFundsCheck  CHAR(10)                  := 'FUND_CHECK';                                            
                v_updatedTransactions TYPE_TRANSACTIONID_COLL  := TYPE_TRANSACTIONID_COLL();                                
                v_transactionids        TYPE_TRANSACTIONID_COLL  := TYPE_TRANSACTIONID_COLL();                          
                v_transactionidsforpl TYPE_TRANSACTIONID_COLL  := TYPE_TRANSACTIONID_COLL();                                
                v_processinglineids     TYPE_PROCESSINGLINEID_COLL := TYPE_PROCESSINGLINEID_COLL();
                v_dueDateProcessId  duedateprocess.duedateprocessid%type;                                               
                v_processingLineFlows TYPE_PROCESSINGLINEFLOWS_COLL := TYPE_PROCESSINGLINEFLOWS_COLL();                 
                v_payments          TYPE_BANKDUEDATEPAYMENT_COLL  := TYPE_BANKDUEDATEPAYMENT_COLL();                    

                v_releasepaymentorder TYPE_PORDUEDATEPROCESS;                                                                    
                v_flw               TYPE_PROCESSINGLINEFLOW_COLL := TYPE_PROCESSINGLINEFLOW_COLL();                      
                v_duepay                TYPE_PROCESSINGLINEPAYMENT;                                                         
                v_duepayments       TYPE_PROCESSINGLINEPAYMT_COLL := TYPE_PROCESSINGLINEPAYMT_COLL();                   
                BEGIN
                    SELECT p.processinglineid BULK COLLECT                                                                  
                    INTO v_processinglineids                                                                                     
                    FROM processingline p                                                                                        
                    INNER JOIN TABLE(p_processinglines) pl                                                                  
                    ON p.processingline    = pl.COLUMN_VALUE;                                                                   
                    v_processingLineFlows := getProcessingLineFlows(v_processinglineids,v_status);                          
                    v_dueDateProcessId := DUEDATE_ID_SEQ.NEXTVAL;                                                               
                    INSERT
                    INTO duedateprocess                                                                                     
                    (
                        duedateprocessid,                                                                                        
                        processingdate,                                                                                     
                        fk_processinglineid
                    )                                                                                                       
                    SELECT v_dueDateProcessId,                                                                              
                    NVL(p_processingdate,SYSDATE),
                    p.COLUMN_VALUE                                                                                          
                    FROM TABLE (v_processinglineids) p;     

                    SELECT TYPE_PORDUEDATEPROCESS(v_dueDateProcessId,TYPE_BANKDUEDATEPAYMENT_COLL())                            
                    INTO v_releasepaymentorder                                                                               
                    FROM DUAL;

                    IF p_portype = 'PrioritizedPOR' THEN                                                                         
                        UPDATE transactions                                                                                     
                        SET paymentstatus     = v_status                                                                            -- If the por type is 'PrioritizedPOR',then paymentstatus is set to 'v_status'
                        WHERE paymentstatus  IN ('RFDD','LAFU','TERE')
                        AND riskStatus IS NULL
                        AND fk_processinglineid IN (SELECT l.COLUMN_VALUE FROM TABLE(v_processinglineids)l)                          
                        AND fk_paymentinfoid IN
                        (SELECT paymentinfoid                                                                                   -- Select paymentinfo ID INNER JOIN the message table                                                                                   
                        FROM paymentinfo p                                                                  
                        INNER JOIN MESSAGE m                                                                                    
                        ON m.messageid         = p.fk_messageid                                                                 -- Message m
                        AND p.releasedate       <= SYSDATE                                                                      -- releasedate is the current date
                        AND m.markettype        = 'BM'                      
                        AND p.prioritized   = 'Y'                               
                        AND p.paymentmethod IN ('TRF') AND categorypurposecode = 'INTC' 
                        AND (p_banksinprocess IS NULL
                        OR initiatorbankid    IN
                        (SELECT b.COLUMN_VALUE FROM TABLE(p_banksinprocess) b
                        ))
                        ) RETURNING transactionsid BULK COLLECT                                                                 -- RETURNING transactionsid BULK COLLECT into v_updatedTransactions
                        INTO v_updatedTransactions;


                    ELSIF p_portype = 'CompletePOR' THEN
                        UPDATE transactions
                        SET paymentstatus     = v_status  
                        WHERE paymentstatus  IN ('RFDD','LAFU','TERE')
                        AND riskStatus IS NULL
                        AND fk_processinglineid IN (SELECT l.COLUMN_VALUE FROM TABLE(v_processinglineids)l)
                        AND fk_paymentinfoid IN
                        (SELECT paymentinfoid
                        FROM paymentinfo p
                        INNER JOIN MESSAGE m
                        ON m.messageid         = p.fk_messageid
                        AND p.releasedate       <= SYSDATE
                        AND m.markettype       = 'BM'    
                        AND (p_banksinprocess IS NULL
                        OR initiatorbankid    IN
                        (SELECT b.COLUMN_VALUE FROM TABLE(p_banksinprocess) b
                        ))
                        ) RETURNING transactionsid BULK COLLECT
                        INTO v_updatedTransactions; 


                    ELSIF p_portype IS NULL THEN 
                        UPDATE transactions
                        SET paymentstatus = v_status
                        WHERE paymentstatus IN (SELECT COLUMN_VALUE FROM TABLE(p_paymentstatuses))
                        AND riskStatus IS NULL
                        AND fk_paymentinfoid IN (
                            SELECT paymentinfoid 
                            FROM paymentinfo 
                            WHERE releasedate <= p_releasedate 
                            AND fk_processinglineid = (SELECT l.COLUMN_VALUE FROM TABLE(v_processinglineids)l) 
                        ) RETURNING transactionsid
                        BULK COLLECT INTO v_updatedTransactions;  
                    END IF;


                    IF v_updatedTransactions.COUNT = 0 THEN
                        raise_application_error (-20302, 'There are no payments to process for processing lines');
                    END IF;


                    INSERT INTO duedateprocesstotransactions (fk_duedateprocessid, fk_transactionsid)
                    SELECT v_dueDateProcessId, ut.COLUMN_VALUE 
                    FROM TABLE(v_updatedTransactions) ut;

                    SELECT TYPE_BANKDUEDATEPAYMENT(initiatorbankid,TYPE_PROCESSINGLINEPAYMT_COLL()) BULK COLLECT
                    INTO v_payments
                    FROM transactions t
                    INNER JOIN paymentinfo p
                    ON p.paymentinfoid = t.fk_paymentinfoid
                    INNER JOIN MESSAGE m
                    ON m.messageid = p.fk_messageid
                    INNER JOIN TABLE(v_updatedTransactions) tid
                    ON t.transactionsid = tid.COLUMN_VALUE
                    GROUP BY m.initiatorbankid;                 


                    FOR i IN v_payments.FIRST..v_payments.LAST
                        LOOP
                            SELECT tid.COLUMN_VALUE BULK COLLECT
                            INTO v_transactionids
                            FROM transactions t
                            INNER JOIN paymentinfo p
                            ON p.paymentinfoid = t.fk_paymentinfoid
                            INNER JOIN MESSAGE m
                            ON m.messageid = p.fk_messageid
                            INNER JOIN TABLE(v_updatedTransactions) tid
                            ON t.transactionsid   = tid.COLUMN_VALUE
                            AND m.initiatorbankid = v_payments(i).bankid;   


                            FOR j IN v_processinglineids.FIRST..v_processinglineids.LAST
                                LOOP    
                                    SELECT TYPE_PROCESSINGLINEPAYMENT(processingline,TYPE_PROCESSINGLINEFLOW_COLL(),TYPE_MESSAGE_COLL(),TYPE_RSVDTLS_COLL())
                                    INTO v_duepay
                                    FROM PROCESSINGLINE
                                    WHERE processinglineid = v_processinglineids(j);      
                                    SELECT TYPE_PROCESSINGLINEFLOW(plf.function,plf.component) BULK COLLECT
                                    INTO v_flw
                                    FROM processinglineflow plf
                                    WHERE fk_processinglineid IN
                                    (SELECT fk_processinglineid                         
                                    FROM transactions t                                 
                                    INNER JOIN TABLE(v_transactionids)ut                
                                    ON t.transactionsid       = ut.COLUMN_VALUE         
                                    AND t.fk_processinglineid = v_processinglineids(j)
                                    );
                                    v_duepay.processinglineflows := v_flw;              


                                     SELECT ut.COLUMN_VALUE BULK COLLECT
                                     INTO v_transactionidsforpl
                                     FROM transactions t
                                     INNER JOIN TABLE(v_transactionids)ut
                                     ON t.transactionsid       = ut.COLUMN_VALUE
                                     AND t.fk_processinglineid = v_processinglineids(j);


                                     v_duepay.reservationRefs := getRsvDtlsForTransactions(v_transactionidsforpl);
                                     v_duepay.messages := pwh_read_pkg.read_duedate_payments(v_transactionidsforpl);
                                     v_duepayments.EXTEND;          
                                     v_duepayments(v_duepayments.COUNT):= v_duepay;

                                END LOOP;

                            v_payments(i).payments := v_duepayments;                     
                        END LOOP;

                    v_releasepaymentorder.payments := v_payments;
                    RETURN v_releasepaymentorder; 
        END;                        
END pwh_release_payment_order_pkg;
/


这是包裹代码:

<FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/shoppingCartIcon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/icon_cart" />

        <ImageView
            android:id="@+id/indicatorIcon"
            android:layout_width="10dp"
            android:layout_height="10dp"
            android:layout_gravity="top|right"
            android:src="#0066ff" />

    </FrameLayout>


为什么会生成错误?

3 个答案:

答案 0 :(得分:2)

更好的方法是在函数开头初始化返回类型的值,函数中的最后一个语句应该返回它。

这种方式只有一个return语句,除非有异常,否则总是调用它。

您的IF语句的嵌套似乎也存在问题。它们嵌套的方式并不能保证会到达RETURN语句。

此处显示代码中的问题,我在其中缩写代码并对其进行注释。

FUNCTION getProcessingLineFlows(                                        
p_processingLineIds IN TYPE_PROCESSINGLINEID_COLL,              
v_status OUT VARCHAR2)
RETURN TYPE_PROCESSINGLINEFLOWS_COLL
  AS
v_processinglineflows TYPE_PROCESSINGLINEFLOWS_COLL :=   TYPE_PROCESSINGLINEFLOWS_COLL();   
v_cnt NUMBER;  
v_processingLineIds TYPE_PROCESSINGLINEID_COLL := TYPE_PROCESSINGLINEID_COLL();             

BEGIN                 

IF v_cnt = p_processingLineIds.count THEN  
SELECT COUNT(DISTINCT flw.processinglineflow.component)                     
INTO v_cnt
FROM TABLE (v_processinglineflows) flw
WHERE flw.processinglineflow.function = 'FUND_CHECK';                   

   IF v_cnt  = 1 THEN                                  
     v_status                           := c_readyForReservationEngine; 
      --return from middle of the function
      --hard to trace and debug   
      --and is the RETURN value initialized?
     RETURN v_processingLineFlows;                                                                     
   END IF;
   --if v_cnt is not 1 then nothing is returned from the branch above this
   --the nested if loops are hard to track
ELSIF v_cnt = 0 THEN                                                        
  SELECT COUNT(flw.processinglineflow.function)                         
  INTO v_cnt                                                                                                                        
  FROM TABLE (v_processinglineflows) flw                                    
  WHERE flw.processinglineflow.function = 'PE_SELECTION';               
     IF v_cnt   = 1 THEN                                                        
        v_status                           := c_readyForPaymentEngine;
        --v_status is initialized but not necessarily your RETURN value        
        RETURN v_processingLineFlows;
     END IF;
 ELSE
    raise_application_error (-20301, 'Invalid processing lines'); 
    --if the no suitable values are found then nothing is returned          
END IF;

答案 1 :(得分:1)

请参阅create function文档以查找正确的定义语法。

CREATE FUNCTION : ORACLE

答案 2 :(得分:1)

确保每个函数中的每个可能的代码路径都有RETURN。例如,在getProcessingLineFlows函数中,您有一个分支开始:

IF v_cnt = p_processingLineIds.count THEN 
    SELECT COUNT(DISTINCT flw.processinglineflow.component)                     
    INTO v_cnt
    FROM TABLE (v_processinglineflows) flw
    WHERE flw.processinglineflow.function = 'FUND_CHECK';                   

    IF v_cnt                              = 1 THEN                                  
        v_status                           := c_readyForReservationEngine;    
        RETURN v_processingLineFlows;                                                                     
    END IF;
ELSIF v_cnt = 0 THEN                                                        
    ...

很难将您的代码读取为格式化,但我相信在不同flw.processinglineflow.component值的数量不完全为1时,此函数将退出而不返回值。我不知道你的数据,或者该值是否可能是1以外的任何值(尽管如果不是,为什么要检查它?)。但这是导致您询问的错误的代码结构。

您需要对所有代码路径执行类似检查,并确保无法返回任何函数结束。