我已经创建了一个带有函数的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>
为什么会生成错误?
答案 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文档以查找正确的定义语法。
答案 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以外的任何值(尽管如果不是,为什么要检查它?)。但这是导致您询问的错误的代码结构。
您需要对所有代码路径执行类似检查,并确保无法返回任何函数结束。