Как использовать функцию, возвращающую Oracle REF_CURSOR в процедуре - PullRequest
1 голос
/ 22 ноября 2011

Я должен написать процедуру Oracle, которая должна вызывать функцию Oracle, возвращающую REF_CURSOR.Функция объявлена ​​так

FUNCTION "IMPACTNET"."TF_CONVERTPARA" (PARASTRING IN NVARCHAR2) RETURN SYS_REFCURSOR
AS
  c SYS_REFCURSOR;
BEGIN
    OPEN c FOR         
        SELECT SUBSTR(element, 1, INSTR(element, '|') - 1)     as key,
               SUBSTR(element, INSTR(element, '|') + 1, 99999) as val
        FROM (
            SELECT REGEXP_SUBSTR(PARASTRING, '[^;]+', 1, LEVEL) element          
                FROM dual      
                CONNECT BY LEVEL < LENGTH(REGEXP_REPLACE(PARASTRING, '[^;]+')) + 1
             );
    RETURN c;     
END;

Можете ли вы сказать мне, что мне нужно написать, чтобы вызвать функцию из моей процедуры?Я хотел бы вставить все возвращенные значения (в форме таблицы с двумя столбцами) в рациональную таблицу.

Заранее спасибо!

1 Ответ

3 голосов
/ 22 ноября 2011

Что-то вроде этого должно работать (очевидно, я предполагаю имена таблиц и имен столбцов и точную логику, которую вы пытаетесь реализовать)

CREATE PROCEDURE some_procedure_name
AS
  l_rc  SYS_REFCURSOR := impactnet.tf_convertpara( <<some string>> );
  l_key VARCHAR2(100);
  l_val VARCHAR2(100);
BEGIN
  LOOP
    FETCH l_rc
      INTO l_key, l_val;
    EXIT WHEN l_rc%notfound;

    INSERT INTO some_table( key_column, val_column )
      VALUES( l_key, l_val );
  END LOOP;
END;

Как указывает Олли,было бы эффективнее сделать BULK COLLECT и FORALL.Если вы имеете дело только с несколькими тысячами строк (поскольку ваша функция просто анализирует данные в строке с разделителями, я предполагаю, что вы ожидаете, что будет возвращено относительно немного строк), разница в производительности, вероятно, минимальна.Но если вы обрабатываете больше данных, разница может быть весьма заметной.В зависимости от версии Oracle и ваших конкретных требований вы можете упростить оператор INSERT в FORALL для вставки записи, а не перечислять каждый столбец из записи по отдельности.

CREATE PROCEDURE some_procedure_name
AS
  TYPE key_val_rec 
    IS RECORD( 
         key  VARCHAR2(100),
         val  VARCHAR2(100)
    );
  TYPE key_val_coll
    IS TABLE OF key_val_rec;

  l_rc   SYS_REFCURSOR := impactnet.tf_convertpara( <<some string>> );
  l_coll key_val_coll;
BEGIN
  LOOP
    FETCH l_rc
      BULK COLLECT INTO l_coll
     LIMIT 100;
    EXIT WHEN l_coll.count = 0;

    FORALL i IN l_coll.FIRST .. l_coll.LAST
      INSERT INTO some_table( key_column, val_column )
        VALUES( l_coll(i).key, l_coll(i).val );
  END LOOP;
END;
...