Oracle
 sql >> база данни >  >> RDS >> Oracle

как да декларирам %ROWTYPE на променлива, която е слабо въведен SYS_REFCURSOR?

Краткият отговор е, че не можете. Ще трябва да дефинирате променлива за всяка колона, която ще бъде върната.

DECLARE
    P_RS SYS_REFCURSOR;
    L_T_COL1 T.COL1%TYPE;
    L_T_COL1 T.COL2%TYPE;
    ...

И след това извлечете в списъка с колони:

FETCH P_RS INTO L_T_COL1, L_T_COL2, ... ;

Това е болезнено, но управляемо, стига да знаете какво очаквате в референтния курсор. Използване на T.* във вашата процедура обаче прави това крехко, тъй като добавянето на колона към таблицата би разрушило кода, който смята, че знае какви колони има и в какъв ред са те. (Можете също да го разбиете между среди, ако таблиците не са изградени последователно - виждал съм места, където подреждането на колоните е различно в различни среди). Вероятно ще искате да сте сигурни, че така или иначе избирате само колоните, които наистина ви интересуват, за да избегнете необходимостта да дефинирате променливи за неща, които никога няма да прочетете.

От 11g можете да използвате DBMS_SQL пакет, за да конвертирате вашия sys_refcursor в DBMS_SQL курсора и можете да го разпитате, за да определите колоните. Само като пример за това, което можете да направите, това ще отпечата стойността на всяка колона във всеки ред с името на колоната:

DECLARE
    P_RS SYS_REFCURSOR;
    L_COLS NUMBER;
    L_DESC DBMS_SQL.DESC_TAB;
    L_CURS INTEGER;
    L_VARCHAR VARCHAR2(4000);
BEGIN
    CAPITALEXTRACT(P_RS => P_RS);
    L_CURS := DBMS_SQL.TO_CURSOR_NUMBER(P_RS);
    DBMS_SQL.DESCRIBE_COLUMNS(C => L_CURS, COL_CNT => L_COLS,
        DESC_T => L_DESC);

    FOR i IN 1..L_COLS LOOP
        DBMS_SQL.DEFINE_COLUMN(L_CURS, i, L_VARCHAR, 4000);
    END LOOP;

    WHILE DBMS_SQL.FETCH_ROWS(L_CURS) > 0 LOOP
        FOR i IN 1..L_COLS LOOP
            DBMS_SQL.COLUMN_VALUE(L_CURS, i, L_VARCHAR);
            DBMS_OUTPUT.PUT_LINE('Row ' || DBMS_SQL.LAST_ROW_COUNT
                || ': ' || l_desc(i).col_name
                || ' = ' || L_VARCHAR);
        END LOOP;
    END LOOP;

    DBMS_SQL.CLOSE_CURSOR(L_CURS);
END;
/

Това не е от голяма практическа полза и за краткост третирам всяка стойност като низ, тъй като така или иначе просто искам да го отпечатам. Разгледайте документите и потърсете примери за по-практични приложения.

Ако искате само няколко колони от вашия ref курсор, предполагам, че бихте могли да обиколите l_desc и запишете позицията, където column_name е всичко, което ви интересува, като числова променлива; след това можете да се обърнете към колоната с тази променлива по-късно, където обикновено ще използвате името в цикъл на курсора. Зависи какво правите с данните.

Но освен ако не очаквате да не знаете реда на колоните, който получавате обратно, което е малко вероятно, тъй като изглежда контролирате процедурата - и ако приемем, че се отървете от .* s – вероятно е много по-добре да намалите върнатите колони до минимума, от който се нуждаете, и просто да ги декларирате поотделно.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SEC_CASE_SENSITIVE_LOGON Оттеглено през 12c

  2. Как да изпълните съхранена процедура на Oracle чрез връзка към база данни

  3. ORA-00054:ресурсът е зает и придобива с указано NOWAIT или времето за изчакване е изтекло

  4. Oracle 12c ИДЕНТИФИЦИРАН ОТ СТОЙНОСТ

  5. NHibernate съпоставяне за Oracle INTERVAL DAY TO SECOND тип данни