oracle 为什么隐式游标会进入无限循环?

kx7yvsdv  于 2023-11-17  发布在  Oracle
关注(0)|答案(2)|浏览(163)

我正在Oracle中编写一个存储PL/SQL函数ListCustomerOrder,它接受客户编号参数。该函数将查找客户发出的所有订单。它必须返回一个字符串,其中包含所有客户的订单编号。所有客户的订单用逗号(,)分隔。如果客户没有发出任何订单,则只需列出客户的编号和名称。客户编号和客户名称出现一次,然后是订单编号。
Eg.

44708 Jack: 864355
41900 May: 4515, 493894, 664641
44988 Tom:

字符串
我想打印一次客户键和客户名称。然后我打印订单键,直到游标qRow中没有值,但看起来不起作用。它只是进入无穷大循环,打印3个无穷大属性。我使用的是隐式游标。
下面是我的代码:

create or replace function ListCustomerOrders (test NUMBER) return varchar2 is 
    prev_key CUSTOMER.C_CUSTKEY%type := 0;    
    emptyList varchar2(32767):='';
    popList varchar2(32767):='';     

begin
FOR qRow in (select C_CUSTKEY, C_NAME, O_ORDERKEY from ORDERS join CUSTOMER on O_CUSTKEY =   C_CUSTKEY where C_CUSTKEY = test)

loop
    if prev_key != qRow.C_CUSTKEY then
        emptyList := (to_char(qRow.C_CUSTKEY) || ' ' || to_char(qRow.C_NAME) ||' : ' );
    end if;

    if qRow.O_ORDERKEY is not null then
       popList := ((to_char(qRow.O_ORDERKEY)) || ', ');
    end if;

    emptyList := emptyList || popList;

    prev_Key := qRow.C_CUSTKEY;

    popList := '';

end loop;

return emptyList;

end ListCustomerOrders;
/
SHOW ERRORS

2skhul33

2skhul331#

为什么要使用光标,尝试使用listagg()和group by进行选择,例如:

SELECT
       C_CUSTKEY
    ,  C_NAME
    ,  LISTAGG(O_ORDERKEY, ', ') WITHIN GROUP (ORDER BY O_ORDERKEY) AS Orders
FROM CUSTOMER 
JOIN ORDERS ON O_CUSTKEY = C_CUSTKEY
WHERE C_CUSTKEY = test
GROUP BY
      C_CUSTKEY
    , C_NAME

字符串

xfyts7mz

xfyts7mz2#

1.如果列表的长度总是在4KB以下,请使用LISTAGG,正如Adrian的答案所示。您可以将key和name列前置(||)到orders字符串中,以获得所需格式的单个字符串。
1.如果必须超过4KB并且需要PL/SQL,则所使用的方法需要游标中的ORDER BY C_CUSTKEY,否则prev_key逻辑将无法工作。
1.这是一个小问题,但如果完全省略popList并将新的部分直接分配给emptyList,代码会更清晰。
1.很明显,这是为了返回一个嵌套的结果表(许多客户行,它们的嵌套订单列表以非关系方式表示为分隔字符串)。但您只返回最后一个客户。如果您从另一个PL/SQL例程调用此例程,则需要将每个客户分配给一个集合,并在最后返回该集合,或者,如果你在SQL中调用它,你可以把它变成一个管道函数,在你完成每个客户的时候管道每个完成的字符串(尽管最后一个选项需要使用SQL类型,这将把你的字符串限制在4KB以内,在这种情况下LISTAGG是上级的)。
1.最后,仔细考虑这是否是正确的方法。分隔字符串是一种非关系结构,在关系数据库中很难使用。很少有合理的理由将多个数据片段组装成一个复合值。

相关问题