Oracle 中返回的函数没有值

问题描述 投票:0回答:1

我在 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 条件吗?或者我错过了什么?

sql plsql oracle11g
1个回答
0
投票

正如 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
错误。如果这是所需的行为,那么您将陷入当前的单独查询。

© www.soinside.com 2019 - 2024. All rights reserved.