【问题标题】:Returning Oracle ref cursor and appending multiple results返回 Oracle 参考游标并附加多个结果
【发布时间】:2009-01-06 16:20:27
【问题描述】:

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

Orders
- orderId
- siteID

Customers
- siteID
- Name

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

现在,我需要编写另一个过程,它接受客户名称并执行 LIKE 查询以获取所有 custId,然后我需要重用 GetOrder 方法来返回找到的 custId 的所有订单,如下所示:

   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 中?正如它现在所写的那样,它会在循环的每个循环中覆盖它。 谢谢!!

【问题讨论】:

  • 次要风格点:如果您要返回多个订单,那么为了清楚起见,GetOrder 应该重命名为GetOrders

标签: oracle sys-refcursor


【解决方案1】:

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

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;

【讨论】:

    【解决方案2】:

    如果查询很简单,我会选择 Tony 的答案。这不仅简单,而且可能比为每个 siteID 执行一个查询执行得更好。

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

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

    如果对接口有意义,一个选项是更改 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;
    

    【讨论】:

    • 请注意,这需要在模式中创建一个新类型(表),这并不总是受欢迎的。
    猜你喜欢
    • 1970-01-01
    • 2012-05-15
    • 1970-01-01
    • 2015-11-13
    • 2011-10-16
    • 1970-01-01
    • 2018-07-31
    • 2018-09-10
    • 2018-03-28
    相关资源
    最近更新 更多