대량 수집 및 forall 문을 사용하려면이 쿼리를 최적화하는 데 도움이 필요합니다. 원본 테이블 (ORIG_xxx)의 모든 데이터를 복사 할 수있는 백업 테이블 (BCK_xxxx)을 만들었지 만 대량으로 변환하는 데 문제가 있습니다. BULK에서 보았던 대부분의 예제에는 % rowtype을 사용하여 테이블 이름과 구조가 이미 정의되어 있습니다. 그러나 필자는 백업 할 테이블이 수백 개이므로 동적으로 테이블 이름을 쿼리해야합니다. 대량없이 하나/삭제 된 데이터의 하나가 수집 삽입하고 시간이 많이 소요이 내 원래의 질의 : 내가 코드를 포함하여 생각하고동적 쿼리 및 테이블 이름이있는 BULK COLLECT/FORALL 문 - Oracle PL/SQL
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 데이터 형식을 선언하십시오. 나는 동적이어야 TABLENAME 이후 ROWTYPE을 사용할 수 없습니다이고 원래 테이블에서 모든 테이블 이름을 나열합니다 내 두 번째 루프의 각 반복에서 변경됩니다 :
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);
당신이 날 도와 내가 할 수있는 방법을 제안 할 수 있습니다 희망 이 코드는 훨씬 간단합니다. 고마워.
감사합니다. 이미 백업 테이블을 만들 때 ctas를 사용했습니다. 나는 truncate를 사용하는 것에 익숙하지만 ddl 문 (자동 커밋)이기 때문에 여기서 사용하는 것을 주저한다. 또한이 것과 비슷한 프로 시저를 만들지 만 원래 테이블의 데이터를 삭제하고 백업 테이블의 레코드를 삽입합니다 .. 잘라 내기를 사용하면 모든 데이터가 백업 테이블. 삭제를 사용하는 다른 방법이 있습니까?또는 커밋 같은 자동 커밋없이 일괄 삭제 같은 것이 있습니까? – mariozelda
truncate를 사용하려는 이유는 모든 삭제 사항으로 리두 로그를 플러드하지 않기 때문입니다. 예, 잘라 내기에서 롤백이 없으므로주의해야합니다. 그러나 그것들은 본질적으로 선택 사항이며 삭제하고 자릅니다. – unleashed