Извлечение PL / SQL sys_refcursor в таблицу записей - PullRequest
0 голосов
/ 22 февраля 2019

Я пытаюсь получить столбцы из ранее возвращенных в таблицу записей.Однако, когда я запускаю код в теле пакета, я получаю следующую ошибку:

ORA-06504: PL/SQL: Return types of Result Set variables or query do not match

Однако, когда я пытаюсь сделать это в окне анонимного блока PL / SQL, я могу успешно извлечь записи, используяМассовая инструкция по сбору.

Вот моя успешная попытка, как я сказал:

DECLARE
--
O_ref SYS_REFCURSOR; 

-- Variable and types declaration.
TYPE REC_TYP is record  (
     column_1     number(8),
     column_2     varchar2(13)
  );

TYPE TAB_TYP is table of REC_TYP;

L_tab_typ   TAB_TYP;
--
BEGIN
  -- 
  open O_ref for 
    select sku,
           upc 
      from upc_ean
     where sku = 2004030; 
    --     
  LOOP
    --
      FETCH O_ref BULK COLLECT into L_tab_typ;
      EXIT WHEN L_tab_typ.COUNT = 0;
      --
      FOR indx IN 1 .. L_tab_typ.COUNT 
      LOOP
        --
        dbms_output.put_line('SKU: ' || L_tab_typ(indx).column_1);
        dbms_output.put_line('UPC: ' || L_tab_typ(indx).column_2);
        --
      END LOOP;
      --
  END LOOP;
  --
  CLOSE O_ref;
  --
END;

Когда я запускаю этот код, я получаю следующий вывод:

SKU: 2004030
UPC: 5601126003439
SKU: 2004030
UPC: 5601126039056

В теле пакета есть следующее:

Почему это не работает в обычном пакете?

FUNCTION GET_STORE_ITEMS(I_store           IN   number
                         ----------- output ------------
                         O_item_data       OUT  NB_TAB_ITEM_DETAIL, -- i want to return a table type after I get the info from the sys_ref
                         ----------- error -------------
                         O_error_message   OUT  VARCHAR2)
  RETURN BOOLEAN IS
    --
    L_tab_type        NB_TAB_ITEM_DETAIL;
    L_sys_ref         SYS_REFCURSOR;
    L_test_sku        number(8);
    --
    CURSOR C_GET_ITEMS IS
      --
      SELECT a.sku
        FROM win_store a
       WHERE a.store = I_store;
    --
  BEGIN
    --
    -- Loop over the fashion skus.
    FOR R_items IN C_GET_ITEMS LOOP
      --
      BEGIN
        --
        IF GET_ITEM_DETAIL(I_store         => I_store,
                           I_sku           => R_items.sku,
                           O_item_data     => L_sys_ref, -- returns a sys_refcursor with the same structure as the type
                           O_error_message => L_error_message) = FALSE THEN
          --
          O_error_message := NB_MESSGE40_SQL.EMESSAGE(L_error_message);
          RETURN FALSE;
          --
        END IF;
        --
        LOOP
        --
          FETCH L_sys_ref BULK COLLECT into L_tab_type; -- It jumps to when others exception
          EXIT WHEN L_tab_type.COUNT = 0;
          --
          FOR indx IN 1 .. L_tab_type.COUNT 
          LOOP
            --
            L_test_sku := L_tab_type(indx).sku;
            --
          END LOOP;
          --
        END LOOP;
        --                      
        END;                                        
        --
    END LOOP;
    --
    RETURN TRUE;
    --
  EXCEPTION
    --
    WHEN OTHERS THEN
      --
      -- ...
      RETURN FALSE;
      --
END GET_STORE_ITEMS;

Спасибо!

1 Ответ

0 голосов
/ 26 февраля 2019

Мне действительно пришлось решить проблему.Перед извлечением sys_refcursor необходимо было объявить тип уровня спецификации пакета, как это было сделано в анонимном блоке.

Сначала в базе данных были созданы типы записей и таблиц:

CREATE OR REPLACE TYPE NB_REC_ITEM_DETAIL AS OBJECT
  (
     column_1     number(8),
     column_2     varchar2(13)
  );

CREATE OR REPLACE TYPE NB_TAB_ITEM_DETAIL AS TABLE OF NB_REC_ITEM_DETAIL; 

Однако эта структура неизвестна для механизма PL / SQL, и поэтому необходимо создать эти структуры данных в спецификации пакета следующим образом:

TYPE REC_TYP is record  (
  column_1     number(8),
  column_2     varchar2(13)
);

TYPE TAB_TYP is table of REC_TYP;

Теперь можно получитьданные из sys_refcursor.

    FUNCTION GET_STORE_ITEMS(I_store           IN   NUMBER,
                         ----------- output ------------
                         O_item_data       OUT  NB_TAB_ITEM_DETAIL,
                         ----------- error -------------
                         O_error_message   OUT  VARCHAR2)
  RETURN BOOLEAN IS
    --
    L_error_message   VARCHAR2(255);
    L_item_data_rec   REC_TYP;
    L_item_detail_ref SYS_REFCURSOR;
    --
    CURSOR C_GET_STORE_ITEMS IS
      --
      SELECT a.sku
        FROM win_store a
       WHERE a.store = I_store;  
    --
  BEGIN
    --
    -- Instantiate output structure object.
    --
    O_item_data := NB_TAB_ITEM_DETAIL();
    --
    -- Loop over the items in the store range.
    --
    FOR R_items IN C_GET_STORE_ITEMS LOOP
      --
      BEGIN
        --
        IF NB_ITEM_INFO_SQL.GET_ITEM_DETAIL(I_store         => I_store,
                                            I_sku           => R_items.sku,
                                            I_ean           => NULL,
                                            O_item_data     => L_item_detail_ref,
                                            O_error_message => L_error_message) = FALSE THEN
          --
          O_error_message := NB_MESSGE40_SQL.EMESSAGE(L_error_message);
          RETURN FALSE;
          --
        END IF;
        --
        -- Fetch info from item_data sys_refcursor to record type.
        --
        FETCH L_item_detail_ref INTO L_item_data_rec;
        EXIT WHEN L_item_detail_ref%NOTFOUND;
        --
        CLOSE L_item_detail_ref; 
        --
        O_item_data.extend();
        O_item_data(O_item_data.last) := nb_rec_item_detail(column_1       => L_item_data_rec.column_1 ,
                                                            column_2       => L_item_data_rec.column_2);
        --
        END;                                              
        --
    END LOOP;
    --
    RETURN TRUE;
    --
  EXCEPTION
    --
    WHEN OTHERS THEN
      -- ...
      RETURN FALSE;
      --
    --
  END GET_STORE_ITEMS;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...