Выполнение большого запроса и возврат строк в Oracle - PullRequest
3 голосов
/ 23 ноября 2011

У меня есть функция, которая получает запрос как параметр (как тип clob) и «выбирает» строки этого запроса для возврата. Мне нужно использовать dbms_sql, потому что размер запроса превышает 32 КБ (~ 150 КБ).

Я застрял в точке извлечения результата:

 -- execute immediate style (does not work with clob):
 EXECUTE IMMEDIATE large_query BULK COLLECT INTO V_TAB ;

 -- dbms_sql style:
 v_upperbound := CEIL(DBMS_LOB.GETLENGTH(large_query)/256);
 FOR i IN 1..v_upperbound
 LOOP
   v_sql(i) := DBMS_LOB.SUBSTR(large_query,256,((i-1)*256)+1);                            
 END LOOP;
 v_cur := DBMS_SQL.OPEN_CURSOR;
 DBMS_SQL.PARSE(v_cur, v_sql, 1, v_upperbound, FALSE, DBMS_SQL.NATIVE);
 v_ret := DBMS_SQL.EXECUTE(v_cur);

 -- NOW WHAT??

Я в Oracle 9i / 10g, поэтому я не могу использовать dbms_slq.to_refcursor.

Есть предложения?

Ответы [ 2 ]

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

Вот пример из документации Oracle. В основном вам нужно dbms_sql.fetch_rows и dbms_sql.column_value:

CREATE TABLE multi_tab (num NUMBER, 
                        dat1 DATE, 
                        var VARCHAR2(24), 
                        dat2 DATE) 

declare
  c       NUMBER;
  d       NUMBER;
  n_tab  DBMS_SQL.NUMBER_TABLE;
  d_tab1 DBMS_SQL.DATE_TABLE;
  v_tab  DBMS_SQL.VARCHAR2_TABLE;
  d_tab2 DBMS_SQL.DATE_TABLE;
  indx NUMBER := 10;
BEGIN

  c := DBMS_SQL.OPEN_CURSOR;
  DBMS_SQL.PARSE(c, 'select * from multi_tab order by 1', DBMS_SQL.NATIVE);

  DBMS_SQL.DEFINE_ARRAY(c, 1, n_tab,  5, indx);
  DBMS_SQL.DEFINE_ARRAY(c, 2, d_tab1, 5, indx);
  DBMS_SQL.DEFINE_ARRAY(c, 3, v_tab,  5, indx);
  DBMS_SQL.DEFINE_ARRAY(c, 4, d_tab2, 5, indx);

  d := DBMS_SQL.EXECUTE(c);

  loop
    d := DBMS_SQL.FETCH_ROWS(c);

    DBMS_SQL.COLUMN_VALUE(c, 1, n_tab);
    DBMS_SQL.COLUMN_VALUE(c, 2, d_tab1);
    DBMS_SQL.COLUMN_VALUE(c, 3, v_tab);
    DBMS_SQL.COLUMN_VALUE(c, 4, d_tab2);

    EXIT WHEN d != 5;
  END LOOP;

  DBMS_SQL.CLOSE_CURSOR(c);
0 голосов
/ 23 ноября 2011

Вот что я сделал, основываясь на ответе:

-- open cursor and execute the query
v_cur := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(v_cur, v_sql, 1, v_upperbound, FALSE, DBMS_SQL.NATIVE);
v_ret := DBMS_SQL.EXECUTE(v_cur);

-- define a column to receive the result (in my case, it's a single varchar2 column)
dbms_sql.define_column(v_cur, 1, V_ROW, 4000); 

-- initialize de result table ( TABELA_REGISTROS_TYPE is a table of varchar2(4000) )
v_tab := TABELA_REGISTROS_TYPE();

-- initializa a counter
v_d := 1; 

-- loop through result rows
LOOP

  -- fetch a row into a varchar2(4000) variable
  EXIT WHEN DBMS_SQL.FETCH_ROWS(v_cur) = 0;
  DBMS_SQL.COLUMN_VALUE(v_cur, 1, V_ROW);

  -- append that row into result set
  V_TAB.EXTEND();
  V_TAB(v_d) := v_row;
  v_d := v_d + 1;

END LOOP;

-- finally close the cursor
DBMS_SQL.close_cursor(v_cur);

-- then return the result set
RETURN V_TAB;
...