我需要帮助优化此查询以使用批量收集和forall语句。我创建了备份表(BCK_xxxx)来复制原始表(ORIG_xxx)中的所有数据,但是我将此转换为批量收集时遇到问题。我在BULK collect中看到的大多数示例包括已使用%rowtype定义表名和结构。但是,我有数百个表要备份,所以我需要我的查询,特别是表名是动态的。这是我的原始查询,逐个插入/删除数据而不进行批量收集并花费大量时间:
DECLARE
--select all table names from backup tables (ex: BCK_tablename)
CURSOR cur_temp_tbl IS
SELECT table_name
FROM all_tables
WHERE OWNER = 'BCKUP'
ORDER BY 1;
--select all table names from original tables (ex: ORIG_tablename)
CURSOR cur_original_tbl IS
SELECT table_name
FROM all_tables
WHERE OWNER = 'ORIG'
ORDER BY 1;
l_tbl_nm VARCHAR2(30 CHAR);
BEGIN
--first loop to delete all tables from backup
FOR a IN cur_temp_tbl LOOP
l_tbl_nm := a.table_name;
EXECUTE IMMEDIATE 'DELETE FROM '|| l_tbl_nm;
l_deleted_cnt := l_deleted_cnt +1;
END LOOP;
--second loop to insert data from original to backup
FOR b IN cur_original_tbl LOOP
l_tbl_nm := b.table_name;
CASE
WHEN INSTR(l_tbl_nm,'ORIG_') > 0 THEN
l_tbl_nm := REPLACE(l_tbl_nm,'ORIG_','BCK_');
ELSE
l_tbl_nm := 'BCK_' || l_tbl_nm;
END CASE;
EXECUTE IMMEDIATE 'INSERT INTO ' || l_tbl_nm || ' SELECT * FROM ' || b.table_name;
l_inserted_cnt := l_inserted_cnt +1;
END LOOP;
dbms_output.put_line('Deleted/truncated tables from backup :' ||l_deleted_cnt);
dbms_output.put_line('No of tables inserted with data from original to backup :' ||l_inserted_cnt);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(SQLERRM);
dbms_output.put_line(l_tbl_nm);
END;
我正在考虑在第二个循环之后添加以下代码,但是我遇到了如何声明'cur_tbl'游标和'l_tbl_data'TABLE数据类型的问题。我无法使用rowtype,因为tablename应该是动态的,并且会在我的第二个循环的每次迭代中更改,它将列出原始表中的所有表名:
TYPE CurTblTyp IS REF CURSOR;
cur_tbl CurTblTyp;
TYPE l_tbl_t IS TABLE OF tablename.%ROWTYPE;
l_tbl_data l_tbl_t ;
OPEN cur_tbl FOR 'SELECT * FROM :s ' USING b.table_name;
FETCH cur_tbl BULK COLLECT INTO l_tbl_data LIMIT 5000;
EXIT WHEN cur_tbl%NOTFOUND;
CLOSE cur_tbl;
FORALL i IN 1 .. l_tbl_data .count
EXECUTE IMMEDIATE 'insert into '||l_tbl_nm||' values (:1)' USING
l_tbl_data(i);
希望你能帮助我,并建议我如何使这段代码更简单。非常感谢。
答案 0 :(得分:0)
除了删除和截断选项之外还有第三个选项:重命名/删除。您重命名旧备份表,重新创建新备份(CTAS)。如果create-insert成功,则删除重命名的表,如果新备份失败,则将先前的旧备份重命名回初始备份名称。您基本上为重做日志交换临时使用的磁盘空间。
您不需要批量处理,CTAS仍然比批量处理更快。
答案 1 :(得分:-1)
您使用过FORCE DELETE吗? 它最初是由Oracle Master J.B.E引入的 它用于删除数据并忽略表可能具有的约束,并且比其他删除语句快得多。
FORCE DELETE FROM <table_name>;