Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

como buscar, excluir, confirmar a partir do cursor


Por que você quer se comprometer em lotes? Isso só vai retardar o seu processamento. A menos que haja outras sessões que estejam tentando modificar as linhas que você está tentando excluir, o que parece problemático por outros motivos, a abordagem mais eficiente seria simplesmente excluir os dados com um único DELETE, ou seja,
DELETE FROM uiv_response_income uri
 WHERE EXISTS( 
    SELECT 1
      FROM (<<bulk_delete_dup query>>) bdd
     WHERE bdd.rowid = uri.rowid
  )

É claro que pode haver uma maneira mais otimizada de escrever isso, dependendo de como a consulta por trás do cursor foi projetada.

Se você realmente deseja eliminar o BULK COLLECT (o que diminuirá substancialmente o processo), você pode usar a sintaxe WHERE CURRENT OF para fazer o DELETE
SQL> create table foo
  2  as
  3  select level col1
  4    from dual
  5  connect by level < 10000;

Table created.

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    cursor c1 is select * from foo for update;
  3    l_rowtype c1%rowtype;
  4  begin
  5    open c1;
  6    loop
  7      fetch c1 into l_rowtype;
  8      exit when c1%notfound;
  9      delete from foo where current of c1;
 10    end loop;
 11* end;
SQL> /

PL/SQL procedure successfully completed.

Esteja ciente, no entanto, que como você precisa bloquear a linha (com a cláusula FOR UPDATE), você não pode colocar um commit no loop. Fazer um commit liberaria os bloqueios que você solicitou com o FOR UPDATE e você obteria um erro ORA-01002:fetch out of sequence
SQL> ed
Wrote file afiedt.buf

  1  declare
  2    cursor c1 is select * from foo for update;
  3    l_rowtype c1%rowtype;
  4  begin
  5    open c1;
  6    loop
  7      fetch c1 into l_rowtype;
  8      exit when c1%notfound;
  9      delete from foo where current of c1;
 10      commit;
 11    end loop;
 12* end;
SQL> /
declare
*
ERROR at line 1:
ORA-01002: fetch out of sequence
ORA-06512: at line 7

Você pode não obter um erro de tempo de execução se remover o bloqueio e evitar a sintaxe WHERE CURRENT OF, excluindo os dados com base no(s) valor(es) obtido(s) do cursor. No entanto, isso ainda está fazendo uma busca no commit, o que é uma prática ruim e aumenta radicalmente as chances de você, pelo menos intermitentemente, obter um erro ORA-01555:snapshot too old. Também será dolorosamente lento em comparação com a única instrução SQL ou a opção BULK COLLECT.
SQL> ed
Wrote file afiedt.buf

  1  declare
  2    cursor c1 is select * from foo;
  3    l_rowtype c1%rowtype;
  4  begin
  5    open c1;
  6    loop
  7      fetch c1 into l_rowtype;
  8      exit when c1%notfound;
  9      delete from foo where col1 = l_rowtype.col1;
 10      commit;
 11    end loop;
 12* end;
SQL> /

PL/SQL procedure successfully completed.

Claro, você também precisa garantir que seu processo seja reiniciável caso você processe algum subconjunto de linhas e tenha um número desconhecido de commits temporários antes que o processo morra. Se o DELETE é suficiente para fazer com que a linha não seja mais retornada do seu cursor, seu processo provavelmente já pode ser reiniciado. Mas, em geral, isso é uma preocupação se você tentar dividir uma única operação em várias transações.