返回 Oracle 引用游标并附加多个结果

发布于 2024-07-10 20:55:13 字数 912 浏览 14 评论 0原文

我有这个问题,希望有人知道答案。 我有一个 Oracle 存储过程,它接受客户 ID 并在 ref_cursor 中返回所有客户的订单。 过于简单化,这就是我所拥有的:

Orders
- orderId
- siteID

Customers
- siteID
- Name

GetOrder(siteID, outCursor) /* returns all orders for a customer */

现在,我需要编写另一个过程,该过程采用客户名称并执行 LIKE 查询来获取所有 custIds,然后我需要重用 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 ? 正如现在所写的那样,它会在循环的每个周期中覆盖它。 谢谢!!

I have this problem I'm hoping someone knows the answer to. I have an oracle stored procedure that takes a customer id and returns all the customer's orders in a ref_cursor. Oversimplifying it, this is what I have:

Orders
- orderId
- siteID

Customers
- siteID
- Name

GetOrder(siteID, outCursor) /* returns all orders for a customer */

Now, I need to write another procedure that takes a customer name and does a LIKE query to get all custIds, then I need to reuse the GetOrder method to return all the orders for the custIds found, something like this:

   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;

My question is, how do I append the return of GetOrder to curReturn in each iteration? As it's written right now it overwrites it in each cycle of the loop.
Thanks!!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

柳絮泡泡 2024-07-17 20:55:13

你不能那样做 - 游标不能被追加或合并。 只需这样做:

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;

You can't do it like that - cursors cannot be appended or merged. Just do this instead:

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;
热鲨 2024-07-17 20:55:13

如果问题很简单,我会说采用托尼的答案。 这不仅简单,而且可能比为每个 siteID 执行一个查询执行得更好。

如果它相当复杂,那么可能值得付出一些额外的努力来重用 GetOrder 过程,这样您只需维护一个查询。

为此,您需要在循环的每次迭代中实际从引用游标中获取数据,并将其放入其他数据结构中。

如果对接口有意义,一种选择是更改 GetOrderbyCustName,将 PL/SQL 索引表作为其输出参数,而不是引用游标。 在循环的每次迭代中附加到该表。

如果确实需要返回引用游标,则可以使用嵌套表类型,然后返回查询该嵌套表的游标。 像这样的东西(未测试的代码):

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;

If the query is simple, I would say go with Tony's answer. This is not only simple but likely to perform better than executing one query for each siteID.

If it is fairly complex then it might be worth some extra effort to reuse the GetOrder procedure so you only have to maintain one query.

To do this, you would need to actually fetch the data from the refcursor on each iteration of the loop, and put it into some other data structure.

One option, if it makes sense for the interface, is to change GetOrderbyCustName to have a PL/SQL index-by table as its output parameter instead of a refcursor. Append to that table on each iteration through the loop.

If you really need to return a refcursor, you can use a nested table type instead and then return a cursor querying that nested table. Something like this (not tested code):

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文