我正在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
型
2条答案
按热度按时间2skhul331#
为什么要使用光标,尝试使用listagg()和group by进行选择,例如:
字符串
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.最后,仔细考虑这是否是正确的方法。分隔字符串是一种非关系结构,在关系数据库中很难使用。很少有合理的理由将多个数据片段组装成一个复合值。