Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 курсор по динамическому селесту  [new]
orabegin
Guest
Пример кода:
--set SERVEROUTPUT on
var l_cur refcursor;
DECLARE
  VARF CLOB;
  TYPE REC_T IS RECORD
  (ZID NUMBER(38,0)
  ,ZFIeld1 DATE);

  TYPE TAB_T IS TABLE OF REC_T;
  VT_TABLE TAB_T;
  V_DOCID number;
  
BEGIN
 
 VARF := 'SELECT ZID,ZFIeld1 from Table';
 EXECUTE IMMEDIATE VARF BULK COLLECT INTO VT_TABLE;-- USING USER;
  
FOR I IN VT_TABLE.FIRST .. VT_TABLE.LAST
LOOP
V_DOCID := VT_TABLE(I).ZID;
EXIT;
end loop;
 
 OPEN :L_CUR FOR
 select V_DOCID from dual;

end;
/
PRINT L_CUR


Проблема такая: получаю в процедуру строку селекта, в которой знаю, что есть необходимые поля. Но все поля не известны(парсить нужно). Т.е селест может быть и таким:
 VARF := 'SELECT ZID,ZFIeld1,ZFIeld2 from Table';

Можно каким-то образом запустить курсор по селекту вида:
VARF := 'SELECT * from Table';
?
9 апр 13, 13:30    [14156317]     Ответить | Цитировать Сообщить модератору
 Re: курсор по динамическому селесту  [new]
Rostislav74
Member

Откуда:
Сообщений: 138
Не знаю что тебе нужно но посмотри в сторону DBMS_SQL...

кусочек кода из пакета для примера...

+
--------------------------------------------------------------------------
-- Процедура формирования списка разбираемых полей 
--------------------------------------------------------------------------
Procedure Sync_12 
is
  sql_ext                              varChar2(2000);                    -- Динамически полученая строка для выполнения
  cur                                  Number;                            -- Код курсорной переменной в системе
  colcnt                               Number;                            -- Количество полей в запросе
  desctab                              DBMS_SQL.desc_tab;                 -- Структура полей в запросе
  exe                                  Number;                            -- Код выполнения в системе
  n_rec                                Number;                            -- Обрабатываемая строка в запросе
  txt                                  dblinks_asup.asup_rn%type;         -- Строка для различных нужд
  ttt                                  Number;
Begin
  sql_ext := SQL_Make('EXT', 0, ', ', 0);
  cur := DBMS_SQL.open_cursor;
  DBMS_SQL.parse(cur, sql_ext, DBMS_SQL.native);
  DBMS_SQL.describe_columns(cur, colcnt, desctab); 
  SQL_Define_Column(cur, desctab);                                        -- Сопоставляем поля с переменными
  exe := DBMS_SQL.execute(cur);                                           -- Открываем курсор
  n_rec := 1;
  -- Идем по открытому курсору 
  Loop
    Exit When DBMS_SQL.fetch_rows(cur) = 0;                               -- Считываем строку если есть
    Set_Fields_SyncType_Value(cur, desctab, fld_ext);                     -- Заполняем массив полей значениями из запроса - важно для Find_Record
    txt := Get_Fields_Str_Value(cur, desctab, 1, fld_ext, 1);
    link_asup_r := Get_DBLink_ASUP(link_r.rn, sync_r.rn, 'EXT', sync_r.ext_table, txt);
    If link_asup_r.rn is Null Then                                        -- линковочной записи нет!
      ttt := Find_Record('ASUP', 2, fld_asup, fld_ext, 0);
      If ttt > 0 Then
        Null;
      end if;
      Add_DBLink_ASUP(link_r.rn, sync_r.rn, sync_r.asup_table, null_key, null, sync_r.ext_table, txt, Null, Null, sync_r.link_master_rn);
    Else                                                                  -- Существует линк-связка данных
      Null;
    end if;

    n_rec := n_rec + 1;
  end Loop;
  DBMS_SQL.close_cursor(cur);                                             -- Закрываем курсор
Exception
  When OTHERS Then                                                        -- Если была ошибка, то проверяем... 
    If DBMS_SQL.is_open(cur) Then                                         -- ...был ли открыт курсор
      DBMS_SQL.close_cursor(cur);                                         -- и если да, то закрываем
    end if;
    Raise;  
end;
9 апр 13, 14:12    [14156627]     Ответить | Цитировать Сообщить модератору
 Re: курсор по динамическому селесту  [new]
ten
Member

Откуда: Екатеринбург
Сообщений: 1672
orabegin,

OPEN :L_CUR FOR 'SELECT ZID,ZFIeld1 from Table'; ?
9 апр 13, 14:33    [14156729]     Ответить | Цитировать Сообщить модератору
 Re: курсор по динамическому селесту  [new]
orabegin
Guest
ten,

В двух словах: есть текст запроса, что он собой представлет я не знаю, кроме одного, что в нём(запросе) присутствуют определённые поля: названия полей и тип мне известен. Нужно выбрать значения этих полей. Т.е. запрос может быть разных видов:
SELECT ZFIELD1
FROM TTABLE T 
--ИЛИ
SELECT T.ZFIELD1
       ,T2.ZFIELD2
FROM TTABLE T 
  INNER JOIN TTABLE1 T1 ON (T1.ZID = T.ZID)
 --или 
SELECT *
FROM TTABLE3 T 
--или ещё какой-нито, но поле ZFIELD1 number(10,0) точно есть

Я вот тут почитал и написал, но букв больно много получилось:
set SERVEROUTPUT on
DECLARE
  SOURCE_CURSOR      INTEGER;  
  SOURCE  CLOB;
  ID_VAR             NUMBER;
  V_TABLENAME         VARCHAR2(250 CHAR);
  V_STMT NUMBER;
  REC_TAB     DBMS_SQL.DESC_TAB;
  COL_CNT     INTEGER;
  COL_NUM INTEGER;
  REC  DBMS_SQL.DESC_REC;

BEGIN
SOURCE_CURSOR := DBMS_SQL.OPEN_CURSOR;
--запрос
SOURCE := 'SELECT * from ALL_OBJECT_TABLES where rownum < 11';
DBMS_SQL.PARSE(SOURCE_CURSOR, 
          SOURCE, 
          DBMS_SQL.NATIVE);
DBMS_SQL.DESCRIBE_COLUMNS(SOURCE_CURSOR, COL_CNT, REC_TAB);
V_STMT := DBMS_SQL.EXECUTE(SOURCE_CURSOR);

--какие поля в какие переменные
FOR COL_NUM IN REC_TAB.FIRST .. REC_TAB.LAST
loop
    IF (COL_NUM IS NOT NULL) THEN
      
        REC := REC_TAB(COL_NUM);
        IF (REC.COL_NAME = 'TABLE_NAME') THEN
        DBMS_SQL.DEFINE_COLUMN(SOURCE_CURSOR, COL_NUM, V_TABLENAME,250);
        exit;
        END IF;
        EXIT WHEN (COL_NUM IS NULL);
    END IF;
END LOOP;

--отбор и показ
WHILE DBMS_SQL.FETCH_ROWS(SOURCE_CURSOR)>0 
LOOP
COL_NUM := REC_TAB.FIRST;
    IF (COL_NUM IS NOT NULL) THEN
      LOOP
        REC := REC_TAB(COL_NUM);
        IF (REC.COL_NAME = 'TABLE_NAME') THEN
        DBMS_SQL.COLUMN_VALUE(SOURCE_CURSOR, COL_NUM, V_TABLENAME);
        DBMS_OUTPUT.PUT_LINE(REC.COL_NAME || ': ' || TO_CHAR(V_TABLENAME));
        exit;
        END IF;
        
        COL_NUM := REC_TAB.NEXT(COL_NUM);
        EXIT WHEN (COL_NUM IS NULL);
      END LOOP;
    END IF;
END LOOP;
DBMS_SQL.CLOSE_CURSOR(SOURCE_CURSOR); 

end;

Может есть более простой ход?
10 апр 13, 14:09    [14161896]     Ответить | Цитировать Сообщить модератору
 Re: курсор по динамическому селесту  [new]
-2-
Member

Откуда:
Сообщений: 15330
orabegin
Нужно выбрать значения этих полей
В dbms_output?
10 апр 13, 14:16    [14161939]     Ответить | Цитировать Сообщить модератору
 Re: курсор по динамическому селесту  [new]
orabegin
Guest
-2-
orabegin
Нужно выбрать значения этих полей
В dbms_output?

Нет, это просто пример. Выбранные значения будут передаваться, например, в процедуру. И в процедуре будет что-то делаться: какая-то логика с апдейтами, инсертами в какие-то таблицы.
10 апр 13, 14:32    [14162059]     Ответить | Цитировать Сообщить модератору
 Re: курсор по динамическому селесту  [new]
-2-
Member

Откуда:
Сообщений: 15330
Если приходит текст запроса, оберни его в ожидаемый текст запроса.
orabegin
какая-то логика
архитектор переживает, что некуда будет тратить ресурсы суперкомпьютера? поэтому надо написать мегауниверсальную процедуру, где засунуть в запрос побольше данных, скрыть структуру запроса за нетипизованным курсором, а потом напишем еще десять процедур, где каждый берет из курсора по какой-то логике.
10 апр 13, 14:46    [14162158]     Ответить | Цитировать Сообщить модератору
 Re: курсор по динамическому селесту  [new]
_Nikotin
Member

Откуда: СПб
Сообщений: 2965
VARF := 'SELECT ZID,ZFIeld1 from('||VARF||')';
EXECUTE IMMEDIATE VARF BULK COLLECT INTO VT_TABLE;
10 апр 13, 14:53    [14162211]     Ответить | Цитировать Сообщить модератору
 Re: курсор по динамическому селесту  [new]
orabegin
Guest
_Nikotin
VARF := 'SELECT ZID,ZFIeld1 from('||VARF||')';
EXECUTE IMMEDIATE VARF BULK COLLECT INTO VT_TABLE;

Спасибо, чё-то не сообразил.
10 апр 13, 15:24    [14162447]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить