我有这个问题我希望有人知道答案。我有一个oracle存储过程,它接受客户ID并返回ref_cursor中的所有客户订单。过度简化它,这就是我所拥有的:
Orders
- orderId
- siteID
Customers
- siteID
- Name
GetOrder(siteID, outCursor) /* returns all orders for a customer */
现在,我需要编写另一个采用客户名称并执行LIKE查询以获取所有custId的过程,然后我需要重用GetOrder方法来返回找到的custIds的所有订单,如下所示:
PROCEDURE GetOrderbyCustName(
p_name IN VARCHAR2,
curReturn OUT sys_refcursor
)
IS
siteid number;
BEGIN
FOR rec in SELECT site_id FROM customers WHERE name LIKE p_name
LOOP
-- This will replace curReturn in each iteration
-- how do I append instead?
GetOrder(rec.site_id,
curReturn
);
END LOOP;
END GetOrderbyCustName;
我的问题是,如何在每次迭代中将GetOrder的返回附加到curReturn?正如它现在所写的那样,它会在循环的每个循环中覆盖它。 谢谢!
答案 0 :(得分:6)
你不能这样做 - 游标不能被追加或合并。只需这样做:
PROCEDURE GetOrderbyCustName(
p_name IN VARCHAR2,
curReturn OUT sys_refcursor
)
IS
BEGIN
OPEN curReturn FOR
SELECT o.orderID, o.siteID
FROM Orders o
JOIN Customers c ON c.siteID = o.siteID
WHERE c.name LIKE p_name;
END GetOrderbyCustName;
答案 1 :(得分:5)
如果查询很简单,我会说托尼的回答。这不仅简单,而且可能比为每个siteID执行一个查询更好。
如果它相当复杂,那么重用GetOrder过程可能需要额外的努力,因此您只需要维护一个查询。
为此,您需要在循环的每次迭代中实际从refcursor中获取数据,并将其放入其他一些数据结构中。
如果对接口有意义,一个选项是将GetOrderbyCustName更改为将PL / SQL索引表作为其输出参数而不是refcursor。通过循环在每次迭代时附加到该表。
如果确实需要返回refcursor,则可以使用嵌套表类型,然后返回查询该嵌套表的游标。像这样的东西(没有经过测试的代码):
CREATE TYPE number_table_type AS TABLE OF NUMBER;
PROCEDURE GetOrderbyCustName(
p_name IN VARCHAR2,
curReturn OUT sys_refcursor
)
IS
cursor_source_table number_table_type := number_table_type();
single_site_cursor sys_refcursor;
orderID NUMBER;
BEGIN
FOR rec in SELECT site_id FROM customers WHERE name LIKE p_name
LOOP
-- This will replace curReturn in each iteration
-- how do I append instead?
GetOrder(rec.site_id,
single_site_cursor
);
-- Fetch all rows from the refcursor and append them to the nested table in memory
LOOP
FETCH single_site_cursor INTO orderID;
EXIT WHEN single_site_cursor%NOTFOUND;
cursor_source_table.extend();
cursor_source_table( cursor_source_table.COUNT+1) := orderID;
END LOOP;
END LOOP;
OPEN curReturn FOR
SELECT * FROM TABLE( cursor_source_table );
END GetOrderbyCustName;