--------------------------------------------------------------------------------
-- Laboratório: DELETE sem WHERE e recuperação com Flashback
--
-- Acompanha o artigo:
--   https://blog.mrdba.com.br/delete-sem-where-oracle
--
-- Autor    : Marcio Mandarino  (mrdba.com.br)
-- Testado  : Oracle Database 19c EE 19.3.0.0.0, non-CDB, NOARCHIVELOG
-- Atualizado: julho/2026
--
-- ATENCAO: rode isto em AMBIENTE DE TESTE. O script apaga dados de proposito.
--          Nao execute em producao.
--
-- Precisa de um ambiente Oracle para rodar? O modulo que ensina a montar o
-- laboratorio completo e gratuito:
--   https://mrdba.com.br/curso-oracle-fundamentals
--------------------------------------------------------------------------------

set linesize 130 pagesize 200 feedback on

prompt
prompt =========================================================
prompt  1. CENARIO: tabela de pedidos com 15.482 linhas
prompt =========================================================

drop table pedidos purge;

create table pedidos (
  id_pedido   number primary key,
  id_cliente  number,
  valor_bruto number(12,2),
  status      varchar2(1)
);

insert into pedidos
select level,
       1000 + mod(level,50),
       round(dbms_random.value(100,5000),2),
       case when mod(level,3)=0 then 'C' else 'A' end
  from dual connect by level <= 15482;
commit;

select count(*) as total_antes from pedidos;

prompt
prompt  Aguarde ~90 segundos antes do proximo bloco.
prompt  Motivo: o Flashback nao consegue voltar para antes do CREATE TABLE.
prompt  Se voce tentar logo apos criar a tabela, recebe ORA-01466.
prompt

-- execute o bloco abaixo depois da espera
prompt =========================================================
prompt  2. O ERRO: delete sem where
prompt =========================================================

delete from pedidos;
commit;

select count(*) as total_depois from pedidos;

prompt
prompt =========================================================
prompt  3. O passado ainda existe no undo?
prompt =========================================================

select count(*) as existia_ha_30s
  from pedidos as of timestamp (systimestamp - interval '30' second);

prompt
prompt =========================================================
prompt  4. RECUPERACAO cirurgica: insert + minus
prompt     (traz de volta so o que falta, sem duplicar)
prompt =========================================================

insert into pedidos
select * from pedidos as of timestamp (systimestamp - interval '30' second)
minus
select * from pedidos;
commit;

select count(*) as total_recuperado from pedidos;

prompt
prompt =========================================================
prompt  5. Flashback Version Query: historico de versoes da linha
prompt     I = insert, U = update, D = delete
prompt =========================================================

select versions_operation, versions_startscn, versions_endscn, id_pedido
  from pedidos versions between timestamp
       (systimestamp - interval '10' minute) and systimestamp
 where id_pedido = 7;

prompt
prompt =========================================================
prompt  6. ALTERNATIVA: flashback table (reverte a tabela inteira)
prompt     CUIDADO: desfaz TUDO no intervalo, nao so o seu delete.
prompt =========================================================

-- alter table pedidos enable row movement;
-- flashback table pedidos to timestamp (systimestamp - interval '30' second);

prompt
prompt =========================================================
prompt  7. Sua janela real de recuperacao
prompt =========================================================

select name, value from v$parameter where name = 'undo_retention';

select begin_time, tuned_undoretention, maxquerylen, undoblks
  from v$undostat
 order by begin_time desc
 fetch first 3 rows only;

prompt
prompt  undo_retention costuma vir 900 (15 minutos) por padrao.
prompt  Entre o erro acontecer e o DBA ser acionado passam horas.
prompt  Como dimensionar isso: veja o artigo sobre undo retention no blog.
prompt

-- limpeza
-- drop table pedidos purge;
