Возврат ссылки на Oracle и добавление нескольких результатов - PullRequest
3 голосов
/ 06 января 2009

У меня есть эта проблема, я надеюсь, что кто-то знает ответ. У меня есть хранимая процедура оракула, которая принимает идентификатор клиента и возвращает все заказы клиента в 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 в каждой итерации? Как он написан сейчас, он перезаписывает его в каждом цикле цикла. Спасибо !!

Ответы [ 2 ]

6 голосов
/ 06 января 2009

Вы не можете так делать - курсоры не могут быть добавлены или объединены. Просто сделайте это вместо:

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;
5 голосов
/ 07 января 2009

Если запрос простой, я бы сказал, ответь Тони. Это не только просто, но и может работать лучше, чем выполнение одного запроса для каждого идентификатора сайта.

Если это довольно сложно, то может потребоваться дополнительное усилие для повторного использования процедуры 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;
...