2017-01-16 7 views
0

Я создаю динамическую процедуру, которая могла бы принять 2 таблицы names.Fetch записей из одной таблицы и после определенной записи (скажем, 100 записей), я должен выдать команду фиксации. И tabName, и temp_tabName всегда одинаковы. Поскольку у меня есть миллиарды записей в первой таблице, я делаю фиксацию после каждых 10000 записей, чтобы избавиться от проблемы с табличным пространством отмены.Получение записи по одному динамически Oracle

До сих пор, что я сделал это:

CREATE OR REPLACE PROCEDURE MyProdecure (
     tabName  IN USER_TABLES.table_name%TYPE, 
     temp_tabName IN USER_TABLES.table_name%TYPE 
    ) 
    IS 
     v_sql   VARCHAR2 (100) := 'select * from ' || tabName; 
     TEMP_CURSOR SYS_REFCURSOR; 
     COUNT   NUMBER (6) := 0; 
    BEGIN 
     OPEN TEMP_CURSOR FOR v_sql; 

     LOOP 
      FETCH TEMP_CURSOR INTO V_ROW; 

     --================================================================================= 

     /* 
      * I need the code here to fetch the 100 record from TEMP_CURSOR into a Variable 
      * and insert into the second table. or one record increment the count and if 
      * count>= 100 commit 
      *What would be the data type of V_ROW. How to fetch the data from V_ROW and complete the insert into command. 
      */ 

     --================================================================================ 
      EXIT WHEN TEMP_CURSOR%NOTFOUND; 
     END LOOP; 

     CLOSE TEMP_CURSOR; 
    END MyProdecure; 
+0

Я не уверен, что это именно то, что вы хотите, но вы можете сделать if, чтобы получить {temp_cursor% rowcount = 100}. Это даст вам момент, когда вы доберетесь до 100-й строки, прочитанной. –

+0

Почему 1 за раз? Почему вы не можете обрабатывать весь комплект сразу? Выполняете ли вы дополнительную обработку по каждой из 100 записей? Это просто кажется неэффективным делать это в цикле, если у вас нет дополнительных ограничений. – xQbert

+3

Это вопрос домашнего задания? В целом, совершать партии не является хорошей практикой. – Boneist

ответ

0

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

Чтобы сделать ваш подход работать, вам нужно будет использовать DBMS_SQL.

Вы рассмотрели вариант следующего, чтобы обойти подавляющее большинство поколения UNDO?

CREATE OR REPLACE PROCEDURE MyProcedure (
     tabName  IN USER_TABLES.table_name%TYPE, 
     temp_tabName IN USER_TABLES.table_name%TYPE 
    ) 
    IS 
    l_log_io NUMBER; 
    C_BLOCK_SIZE NUMBER := 8192; -- assuming 8192 byte block size 
    l_undo_bytes NUMBER; 
BEGIN 
    EXECUTE IMMEDIATE 'INSERT /*+ APPEND */ INTO ' || temp_tabName || 
    ' SELECT * FROM ' || tabName; 

    select t.log_io, t.used_ublk*C_BLOCK_SIZE undo_bytes 
    into l_log_io, l_undo_bytes 
    from v$transaction t 
    where t.addr = (SELECT s.taddr FROM v$session s WHERE s.sid = USERENV('SID')); 

    dbms_output.put_line('Undo bytes used: ' || l_undo_bytes); 
END; 

INSERT /*+ APPEND */ поставляется с целым рядом оговорок, которые вы должны смотреть в перед его использованием, но это может быть намного более простым способом достижения этой цели.