sexta-feira, 17 de outubro de 2014

Oracle/PL-SQL - Delete com BULK

Para operações de delete em grandes tabelas, uma opção é utilizar o conceito de BULK o que garante não só uma melhor performance no DELETE com também diminui a quantidade de controles por causa dos COMMITs. Um exemplo seria:

CREATE OR REPLACE PROCEDURE PR_PURGE IS

CURSOR cdr_cur IS
SELECT ROWID FROM <TABELA> c where <CONDICAO>;

TYPE cdr_data IS TABLE OF ROWID INDEX BY BINARY_INTEGER;
cdr cdr_data;

BEGIN
OPEN cdr_cur;
LOOP
     cdr.DELETE;

     FETCH cdr_cur BULK COLLECT INTO cdr LIMIT <LIMITE>;  --LIMITE

     IF cdr.COUNT>0 THEN
          FORALL j IN 1..cdr.COUNT
          DELETE FROM <TABELA> WHERE ROWID=cdr(j);
          COMMIT;
     ELSE
          EXIT;
     END IF;
END LOOP;

CLOSE cdr_cur;
COMMIT;

EXCEPTION
     WHEN OTHERS THEN
          IF cdr_cur%ISOPEN THEN CLOSE cdr_cur; END IF;
     
END;

onde:
<TABELA> - Tabela que será manipulada
<CONDICAO> - Condição de pesquisa/seleção
<LIMITE> - Quantidade de registros transacionados por vez

exemplo:

CREATE OR REPLACE PROCEDURE PR_PURGE IS

CURSOR cdr_cur IS
SELECT ROWID FROM TABELA_A c where c.DATA > '20141201';

TYPE cdr_data IS TABLE OF ROWID INDEX BY BINARY_INTEGER;
cdr cdr_data;

BEGIN
OPEN cdr_cur;
LOOP
     cdr.DELETE;

     FETCH cdr_cur BULK COLLECT INTO cdr LIMIT 100000;

     IF cdr.COUNT>0 THEN
          FORALL j IN 1..cdr.COUNT
          DELETE FROM TABELA_A WHERE ROWID=cdr(j);
          COMMIT;
     ELSE
          EXIT;
     END IF;
END LOOP;

CLOSE cdr_cur;
COMMIT;

EXCEPTION
     WHEN OTHERS THEN
          IF cdr_cur%ISOPEN THEN CLOSE cdr_cur; END IF;
     
END;