我正在创建一个可以接受2个表名的动态过程。从一个表中获取记录,在某个记录之后(假设有100个记录)我必须发出commit命令。 tabName和temp_tabName都是相同的。因为我在第一个表中有数十亿条记录,所以我在每10000条记录之后进行提交,以便摆脱撤销表空间问题。
直到现在我所做的是:
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 :(得分: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 */
附带了一些在使用之前应该考虑的警告,但这可能是实现目标的一种更简单的方式。