我在 Oracle 数据库中创建了第一个函数,但返回错误 (ORA-06503):
ORA-06503:PL/SQL:返回的函数没有值
function GetNumberOfReceipt(psID varchar2) return number is
nID_Order number;
nID_Bill number;
nID_DeliveryNO number;
nID_WithoutDeliveryNO number;
nID number;
nExists number;
begin
select count(*) into nExists from <mytable> where <mywhereclause> = psID;
--query blocks
--ORDER
select id into nID_Order from <mytables> where <mywhereclause> = psID group by id;
--PL
select id into nID_Bill from <mytables> where <mywhereclause> = psID group by id;
--DeliveryNote
select id into nID_DeliveryNO from <mytables> where <mywhereclause>=psID;
--DeriveryNoteWithout
select id into nID_WithoutDeliveryNO from <mytables> where <mywhereclause> =psID;
--Format multiple values/IDs
select listagg(ID,',') within group(order by ID ) into nID from (
select nID_Order as ID from dual
union all
select nID_Bill as ID from dual
union all
select nID_DeliveryNO as ID from dual
union all
select nID_WithoutDeliveryNO as ID from dual
group by nID_Order,nID_Bill,nID_DeliveryNO,nID_WithoutDeliveryNO);
IF nExists=0 THEN
--raise
<myerrormsg> -- pckg procedure
ELSE
return nID;
END IF;
exception
when no_data_found then
nID := 0;
end GetNumberOfReceipt;
在查询块中,查询正在运行,因为我测试了每个查询。
我应该删除 if 条件吗?或者我错过了什么?
正如 Koen 在评论中指出的那样,问题在于您有一个不会引发异常或返回值的异常块。
但是,您的函数流程并没有真正意义 - 为什么您要检查订单 id 是否存在,但直到最后才对其执行任何操作?
另外,为什么将所有 id 收集到它们的各个变量中只是为了编写一个虚拟查询来连接它们?为什么不在一个查询中完成所有这些?
我认为如果你将其重写为如下形式,你的函数会更有效:
CREATE OR REPLACE FUNCTION getnumberofreceipt(psid VARCHAR2) RETURN NUMBER IS
nid NUMBER;
nexists NUMBER;
BEGIN
SELECT COUNT(*)
INTO nexists
FROM < mytable >
WHERE < mywhereclause > = psid;
IF nexists = 0 -- Moved the IF statement here, to avoid doing unnecessary work when we know the order id doesn't exist
THEN
-- either raise an exception here via RAISE_APPLICATION_ERROR(), or set the nid variable to a dummy value, depending on your requirements
ELSE
-- combined all your queries into one. Depending on the tables and join conditions in each subquery, it may be possible to combine the queries further,
-- but it's difficult to say because you've over-simplified your queries.
WITH orders AS (SELECT ID -- if you're only selecting this one column, you can remove the group by and just use DISTINCT instead
FROM < mytables >
WHERE < mywhereclause > = psid
GROUP BY ID),
pl AS (SELECT id -- if you're only selecting this one column, you can remove the group by and just use DISTINCT instead
FROM < mytables >
WHERE < mywhereclause > = psid
GROUP BY ID),
deliverynote AS (SELECT ID
FROM < mytables >
WHERE < mywhereclause >= psid),
DeriveryNoteWithout AS (SELECT id
INTO nid_withoutdeliveryno
FROM < mytables >
WHERE < mywhereclause > = psid)
--Format multiple values/IDs
SELECT listagg(id, ',') within GROUP(ORDER BY id)
INTO nid
FROM (SELECT id
FROM orders
UNION -- Using UNIONs instead of UNION ALLs because it seems we only want unique IDs
SELECT id
FROM pl
UNION
SELECT id
FROM deliverynote
UNION
SELECT id
FROM deriverynotewithout);
END IF;
RETURN nid; -- Arguably, it's good practice to have a single point of return in the main block
-- i.e. set the variable at the relevant points and then return it at the end.
END getnumberofreceipt;
/
注意这将处理这样的情况:对于给定的
id
,您可能会返回多个 psid
,而您的原始函数会引发 TOO_MANY_ROWS
错误。如果这是所需的行为,那么您将陷入当前的单独查询。