Recursividade - Registro pai, filhos, netos, bisnetos...
Autor: Jaxmim | Publicado: 2009-12-01T16:26:00-08:00

O problema da vez foi o seguinte: Numa base Oracle 11g, foi identificado um furo em uma regra de negócio que consequentemente afetou a aplicação e o banco de dados. Ocorreu que uma informação pôde ser gravada duas vezes, ou seja, ficou duplicada em termos de negócio.Identificado o problema, o cliente pediu uma query para varrer todos os registros que referenciavam de alguma forma aquele ID específico.O agravante era que o sistema já estava em produção e em momento nenhum poderia sair do ar.Achei que alterar as constraints para conseguir um 'Delete Cascade' seria a solução = FAIL.Então, analisei bem a situação e o padrão de nomenclatura dos objetos deste banco. Como existia um padrão bem definido, carreguei em tabelas temporárias as informações que precisava e depois saí montando as queries. Vamos lá:Tudo começava em um Projeto (TB_PROJETO). Então no primeiro nível carreguei as tabelas e campos pai e tabelas e campos filhos:-- CARREGAR NIVEL 1 = pai + filhosCREATE GLOBAL TEMPORARY TABLE TB_ADM_NIVEL_1 ASSELECT  REPLACE(R_CONSTRAINT_NAME,'PK_', '') AS TABELA_PAI_0,     REPLACE(R_CONSTRAINT_NAME AS CAMPO_PAI_0, 'PK_', 'ID_') AS CAMPO_PAI_0,     TABLE_NAME AS TABELA_FILHA_1,     REPLACE(TABLE_NAME, 'TB', 'ID') AS CAMPO_FILHA_1FROM    ALL_CONSTRAINTS WHERE OWNER = 'O-W-N-E-R' AND CONSTRAINT_TYPE = 'R' AND replace(R_CONSTRAINT_NAME,'PK_', '') = 'TB_PROJETO' ORDER BY TABLE_NAME;No segundo nível carreguei as tabelas e campos que são filhas no nível 1 e agora pai no nível 2:-- CARREGAR NIVEL 2 = filhos + netosCREATE GLOBAL TEMPORARY TABLE TB_ADM_NIVEL_2 ASSELECT  REPLACE(R_CONSTRAINT_NAME,'PK_', '') AS TABELA_PAI_1,     REPLACE(R_CONSTRAINT_NAME, 'PK_TB', 'ID' AS CAMPO_PAI_1,     TABLE_NAME AS TABELA_FILHA_2,     REPLACE(TABLE_NAME, 'TB', 'ID') AS CAMPO_FILHA_2FROM ALL_CONSTRAINTS WHERE OWNER = 'O-W-N-E-R' AND CONSTRAINT_TYPE = 'R' AND replace(R_CONSTRAINT_NAME,'PK_', '') IN (SELECT TABELA_FILHA_1 FROM TB_ADM_NIVEL_1 WHERE TABELA_FILHA_1 <> TABELA_PAI_0);-- CARREGAR NIVEL 3 = netos + bisnetosCREATE GLOBAL TEMPORARY TABLE TB_ADM_NIVEL_3 ASSELECT  REPLACE(R_CONSTRAINT_NAME,'PK_', '') AS TABELA_PAI_2,     REPLACE(R_CONSTRAINT_NAME, 'PK_TB', 'ID') AS CAMPO_PAI_2,     TABLE_NAME AS TABELA_FILHA_3,     REPLACE(TABLE_NAME, 'TB', 'ID') AS CAMPO_FILHA_3FROM ALL_CONSTRAINTS WHERE OWNER = 'O-W-N-E-R' AND CONSTRAINT_TYPE = 'R' AND replace(R_CONSTRAINT_NAME,'PK_', '') IN (SELECT TABELA_FILHA_2 FROM TB_ADM_NIVEL_2 WHERE TABELA_FILHA_2 <> TABELA_PAI_1);-- CARREGAR NIVEL 4 = bisnetos + tataranetosCREATE GLOBAL TEMPORARY TABLE TB_ADM_NIVEL_4 ASSELECT  REPLACE(R_CONSTRAINT_NAME,'PK_', '') AS TABELA_PAI_3,     REPLACE(R_CONSTRAINT_NAME, 'PK_TB', 'ID') AS CAMPO_PAI_3,     TABLE_NAME AS TABELA_FILHA_4,     REPLACE(TABLE_NAME, 'TB', 'ID') AS CAMPO_FILHA_4FROM ALL_CONSTRAINTS WHERE OWNER = 'O-W-N-E-R' AND CONSTRAINT_TYPE = 'R' AND replace(R_CONSTRAINT_NAME,'PK_', '') IN (SELECT TABELA_FILHA_3 FROM TB_ADM_NIVEL_3 WHERE TABELA_FILHA_3 <> TABELA_PAI_2);-- CARREGAR NIVEL 5 = VAZIOCREATE GLOBAL TEMPORARY TABLE TB_ADM_NIVEL_5 ASSELECT  REPLACE(R_CONSTRAINT_NAME,'PK_', '') AS TABELA_PAI_4,     REPLACE(R_CONSTRAINT_NAME, 'PK_TB', 'ID') AS CAMPO_PAI_4,     TABLE_NAME AS TABELA_FILHA_5,     REPLACE(TABLE_NAME, 'TB', 'ID') AS CAMPO_FILHA_5FROM ALL_CONSTRAINTS WHERE OWNER = 'O-W-N-E-R' AND CONSTRAINT_TYPE = 'R' AND replace(R_CONSTRAINT_NAME,'PK_', '') IN (SELECT TABELA_FILHA_4 FROM TB_ADM_NIVEL_4 WHERE TABELA_FILHA_4 <> TABELA_PAI_3);Criei tabelas até o nível em que não existia mais registros no último nível. No caso, a tabela TB_ADM_NIVEL_5 não possui nenhum registro e portanto pôde ser dropada. Trabalhei apenas com as tabelas com informações de nível 0 a 4.DROP TABLE TB_ADM_NIVEL_5;Assim, recursivamente, da tabela 4 até a 1, usei uma query para carregar uma tabela com a ordem dos registros nas tabelas que deveriam ser apagados. Uni cada query pelo comando UNION para que ele fizesse a eliminação de possíveis linhas repetidas. Definir estas querys, foi a parte mais delicada da solução pois exigiu um entendimento quanto à lógica dos relacionamentos aplicados. Sei que o uso de subquery não é uma boa prática, mas neste caso pontual, serviu muito bem.CREATE GLOBAL TEMPORARY TABLE TB_SCRIPT_DEL_PROJETOAS-- APAGAR REGISTROS DAS TABELAS FILHAS NIVEL 4SELECT  DISTINCT     'DELETE ' || TN4.TABELA_FILHA_4 ||     ' WHERE ' || TN4.TABELA_FILHA_4 || '.' || TN4.CAMPO_PAI_3 ||     ' IN (SELECT ' || TN3.TABELA_FILHA_3 || '.' || TN4.CAMPO_PAI_3 ||     ' FROM ' || TN3.TABELA_FILHA_3 ||     ' WHERE ' || TN3.TABELA_FILHA_3 || '.' || TN3.CAMPO_PAI_2 ||     ' IN (SELECT ' || TN2.TABELA_FILHA_2 || '.' || TN3.CAMPO_PAI_2 ||     ' FROM ' || TN2.TABELA_FILHA_2 ||     ' WHERE ' || TN2.TABELA_FILHA_2 || '.' || TN2.CAMPO_PAI_1 ||     ' IN (SELECT ' || TN1.TABELA_FILHA_1 || '.' || TN2.CAMPO_PAI_1 ||     ' FROM ' || TN1.TABELA_FILHA_1 ||     ' WHERE ' || TN1.TABELA_FILHA_1 || '.ID_PROJETO = NUMERO)));' AS SCRIPT, TN4.TABELA_FILHA_4 AS TABELA, 4 AS NIVELFROM    TB_ADM_NIVEL_1 TN1, TB_ADM_NIVEL_2 TN2, TB_ADM_NIVEL_3 TN3, TB_ADM_NIVEL_4 TN4WHERE   TN1.CAMPO_FILHA_1 = TN2.CAMPO_PAI_1AND     TN2.CAMPO_FILHA_2 = TN3.CAMPO_PAI_2AND     TN3.CAMPO_FILHA_3 = TN4.CAMPO_PAI_3UNION-- APAGAR REGISTROS DAS TABELAS FILHAS NIVEL 3SELECT  DISTINCT     'DELETE ' || TN3.TABELA_FILHA_3 ||     ' WHERE ' || TN3.TABELA_FILHA_3 || '.' || TN3.CAMPO_PAI_2 ||     ' IN (SELECT ' || TN2.TABELA_FILHA_2 || '.' || TN3.CAMPO_PAI_2 ||     ' FROM ' || TN2.TABELA_FILHA_2 ||     ' WHERE ' || TN2.TABELA_FILHA_2 || '.' || TN2.CAMPO_PAI_1 ||     ' IN (SELECT ' || TN1.TABELA_FILHA_1 || '.' || TN2.CAMPO_PAI_1 ||     ' FROM ' || TN1.TABELA_FILHA_1 ||     ' WHERE ' || TN1.TABELA_FILHA_1 || '.ID_PROJETO = NUMERO));' AS SCRIPT, TN3.TABELA_FILHA_3 AS TABELA, 3 AS NIVELFROM    TB_ADM_NIVEL_1 TN1, TB_ADM_NIVEL_2 TN2, TB_ADM_NIVEL_3 TN3WHERE   TN1.CAMPO_FILHA_1 = TN2.CAMPO_PAI_1AND     TN2.CAMPO_FILHA_2 = TN3.CAMPO_PAI_2UNION-- APAGAR REGISTROS DAS TABELAS FILHAS NIVEL 2SELECT  DISTINCT     'DELETE ' || TN2.TABELA_FILHA_2 ||     ' WHERE ' || TN2.TABELA_FILHA_2 || '.' || TN2.CAMPO_PAI_1 ||     ' IN (SELECT ' || TN1.TABELA_FILHA_1 || '.' || TN2.CAMPO_PAI_1 ||     ' FROM ' || TN1.TABELA_FILHA_1 ||     ' WHERE ' || TN1.TABELA_FILHA_1 || '.ID_PROJETO = NUMERO);' AS SCRIPT, TN2.TABELA_FILHA_2 AS TABELA, 2 AS NIVELFROM    TB_ADM_NIVEL_1 TN1, TB_ADM_NIVEL_2 TN2WHERE   TN1.CAMPO_FILHA_1 = TN2.CAMPO_PAI_1UNION-- APAGAR REGISTROS DAS TABELAS FILHAS NIVEL 1 SEM FILHOS NIVEL 2SELECT     'DELETE ' || TABELA_FILHA_1 ||     ' WHERE ' || CAMPO_PAI_0 || ' = NUMERO;' AS SCRIPT, TABELA_FILHA_1 AS TABELA, 1 AS NIVELFROM    TB_ADM_NIVEL_1WHERE   TABELA_FILHA_1 <> 'TB_PROJETO'UNION-- SCRIPT PARA APAGAR REGISTRO DA TABELA DE PROJETOSELECT 'DELETE FROM TB_SGP_PROJETO WHERE ID_PROJETO = NUMERO;' AS SCRIPT, 'TB_SGP_PROJETO' AS TABELA, 0 AS NIVEL FROM DUAL;Finalmente, rodei o script que realmente importava:-- PARA RECUPERAR SCRIPT DE EXCLUSÃO - EXECUTAR O RESULTADOSELECT SCRIPT FROM TB_SCRIPT_DEL_PROJETO ORDER BY NIVEL DESC;Daí foi só colocar o retorno desse script em um bloco anônimo com uma variável chamada NUMERO. De acordo com o número indicado, o script no bloco varre as tabelas apagando todas as referencias em tabelas bisnetas, netas, filhas e finalmente pai:-- INFORMAR O NUMERO DO PROJETO A SER DELETADO AQUIDECLARE NUMERO NUMBER := 7777;BEGIN DELETE TB_LANC_ITEM_ORC WHERE TB_LANC_ITEM_ORC.ID_ITEM_ORC IN (SELECT TB_ITEM_ORC.ID_ITEM_ORC FROM TB_ITEM_ORC WHERE TB_ITEM_ORC.ID_ACAO_PARC IN (SELECT TB_ACAO_PARC.ID_ACAO_PARC FROM TB_ACAO_PARC WHERE TB_ACAO_PARC.ID_PROJETO_PARC IN (SELECT TB_PROJ_PARC.ID_PROJETO_PARC FROM TB_PROJ_PARC WHERE TB_PROJ_PARC.ID_PROJETO = NUMERO))) OR TB_LANC_ITEM_ORC.ID_ITEM_ORC IN (SELECT TB_ITEM_ORC.ID_ITEM_ORC FROM TB_ITEM_ORC WHERE TB_ITEM_ORC.ID_ACAO_PARC IN (SELECT TB_ACAO_PARC.ID_ACAO_PARC FROM TB_ACAO_PARC WHERE TB_ACAO_PARC.ID_ACAO IN (SELECT TB_ACAO.ID_ACAO FROM TB_ACAO WHERE TB_ACAO.ID_PROJETO = NUMERO))); DELETE TB_APR_MUD_ACAO_EVENTO WHERE TB_APR_MUD_ACAO_EVENTO.ID_MUD_EVENTO IN (SELECT TB_MUD_EVENTO.ID_MUD_EVENTO FROM TB_MUD_EVENTO WHERE TB_MUD_EVENTO.ID_EVENTO_ACAO IN (SELECT TB_EVENTO.ID_EVENTO_ACAO FROM TB_EVENTO WHERE TB_EVENTO.ID_ACAO IN (SELECT TB_ACAO.ID_ACAO FROM TB_ACAO WHERE TB_ACAO.ID_PROJETO = NUMERO))) OR TB_APR_MUD_ACAO_EVENTO.ID_MUD_EVENTO IN (SELECT TB_MUD_EVENTO.ID_MUD_EVENTO FROM TB_MUD_EVENTO WHERE TB_MUD_EVENTO.ID_CONJ_MUD IN (SELECT TB_CONJ_MUD.ID_CONJ_MUD FROM TB_CONJ_MUD WHERE TB_CONJ_MUD.ID_PROJETO = NUMERO)); DELETE TB_APR_MUD_ACAO_NCM WHERE TB_APR_MUD_ACAO_NCM.ID_MUD_ACAO_NCM IN (SELECT TB_MUD_ACAO_NCM.ID_MUD_ACAO_NCM FROM TB_MUD_ACAO_NCM WHERE TB_MUD_ACAO_NCM.ID_ACAO_NCM IN (SELECT TB_ACAO_NCM.ID_ACAO_NCM FROM TB_ACAO_NCM WHERE TB_ACAO_NCM.ID_ACAO IN (SELECT TB_ACAO.ID_ACAO FROM TB_ACAO WHERE TB_ACAO.ID_PROJETO = NUMERO))) OR TB_APR_MUD_ACAO_NCM.ID_MUD_ACAO_NCM IN (SELECT TB_MUD_ACAO_NCM.ID_MUD_ACAO_NCM FROM TB_MUD_ACAO_NCM WHERE TB_MUD_ACAO_NCM.ID_CONJ_MUD IN (SELECT TB_CONJ_MUD.ID_CONJ_MUD FROM TB_CONJ_MUD WHERE TB_CONJ_MUD.ID_PROJETO = NUMERO)); DELETE TB_APR_MUD_ITEM_ORC_ WHERE TB_APR_MUD_ITEM_ORC_.ID_MUD_ITEM_ORC IN (select ID_MUD_ITEM_ORC from TB_MUD_ITEM_ORC WHERE ID_ITEM_ORC IN (SELECT TB_ITEM_ORC.ID_ITEM_ORC FROM TB_ITEM_ORC WHERE TB_ITEM_ORC.ID_ACAO_PARC IN (SELECT TB_ACAO_PARC.ID_ACAO_PARC FROM TB_ACAO_PARC WHERE TB_ACAO_PARC.ID_ACAO IN (SELECT TB_ACAO.ID_ACAO FROM TB_ACAO WHERE TB_ACAO.ID_PROJETO = NUMERO)))); DELETE TB_APR_MUD_PROJ_MERCADO WHERE TB_APR_MUD_PROJ_MERCADO.ID_MUD_PROJ_OBJ_MERCADO IN (SELECT TB_MUD_PROJ_OBJ_MERCADO.ID_MUD_PROJ_OBJ_MERCADO FROM TB_MUD_PROJ_OBJ_MERCADO WHERE TB_MUD_PROJ_OBJ_MERCADO.ID_PROJ_OBJ_MERCADO IN (SELECT TB_PROJ_OBJ_MERCADO.ID_PROJ_OBJ_MERCADO FROM TB_PROJ_OBJ_MERCADO WHERE TB_PROJ_OBJ_MERCADO.ID_PROJETO_PAIS IN (SELECT TB_PROJ_PAIS.ID_PROJETO_PAIS FROM TB_PROJ_PAIS WHERE TB_PROJ_PAIS.ID_PROJETO = NUMERO))) OR TB_APR_MUD_PROJ_MERCADO.ID_MUD_PROJ_OBJ_MERCADO IN (SELECT TB_MUD_PROJ_OBJ_MERCADO.ID_MUD_PROJ_OBJ_MERCADO FROM TB_MUD_PROJ_OBJ_MERCADO WHERE TB_MUD_PROJ_OBJ_MERCADO.ID_CONJ_MUD IN (SELECT TB_CONJ_MUD.ID_CONJ_MUD FROM TB_CONJ_MUD WHERE TB_CONJ_MUD.ID_PROJETO = NUMERO)) OR TB_APR_MUD_PROJ_MERCADO.ID_MUD_PROJ_OBJ_MERCADO IN (SELECT TB_MUD_PROJ_OBJ_MERCADO.ID_MUD_PROJ_OBJ_MERCADO FROM TB_MUD_PROJ_OBJ_MERCADO WHERE TB_MUD_PROJ_OBJ_MERCADO.ID_PROJETO_PAIS IN (SELECT TB_PROJ_PAIS.ID_PROJETO_PAIS FROM TB_PROJ_PAIS WHERE TB_PROJ_PAIS.ID_PROJETO = NUMERO)); DELETE TB_APR_MUD_ACAO_PARC WHERE TB_APR_MUD_ACAO_PARC.ID_MUD_ACAO_PARC IN (SELECT TB_MUD_ACAO_PARC.ID_MUD_ACAO_PARC FROM TB_MUD_ACAO_PARC WHERE TB_MUD_ACAO_PARC.ID_ACAO_PARC IN (SELECT TB_ACAO_PARC.ID_ACAO_PARC FROM TB_ACAO_PARC WHERE TB_ACAO_PARC.ID_PROJETO_PARC IN (SELECT TB_PROJ_PARC.ID_PROJETO_PARC FROM TB_PROJ_PARC WHERE TB_PROJ_PARC.ID_PROJETO = NUMERO))) OR TB_APR_MUD_ACAO_PARC.ID_MUD_ACAO_PARC IN (SELECT TB_MUD_ACAO_PARC.ID_MUD_ACAO_PARC FROM TB_MUD_ACAO_PARC WHERE TB_MUD_ACAO_PARC.ID_ACAO_PARC IN (SELECT TB_ACAO_PARC.ID_ACAO_PARC FROM TB_ACAO_PARC WHERE TB_ACAO_PARC.ID_ACAO IN (SELECT TB_ACAO.ID_ACAO FROM TB_ACAO WHERE TB_ACAO.ID_PROJETO = NUMERO))) OR TB_APR_MUD_ACAO_PARC.ID_MUD_ACAO_PARC IN (SELECT TB_MUD_ACAO_PARC.ID_MUD_ACAO_PARC FROM TB_MUD_ACAO_PARC WHERE TB_MUD_ACAO_PARC.ID_CONJ_MUD IN (SELECT TB_CONJ_MUD.ID_CONJ_MUD FROM TB_CONJ_MUD WHERE TB_CONJ_MUD.ID_PROJETO = NUMERO)) OR TB_APR_MUD_ACAO_PARC.ID_MUD_ACAO_PARC IN (SELECT TB_MUD_ACAO_PARC.ID_MUD_ACAO_PARC FROM TB_MUD_ACAO_PARC WHERE TB_MUD_ACAO_PARC.ID_PROJETO_PARC IN (SELECT TB_PROJ_PARC.ID_PROJETO_PARC FROM TB_PROJ_PARC WHERE TB_PROJ_PARC.ID_PROJETO = NUMERO)); DELETE TB_MUD_ITEM_ORC WHERE TB_MUD_ITEM_ORC.ID_ITEM_ORC IN (SELECT TB_ITEM_ORC.ID_ITEM_ORC FROM TB_ITEM_ORC WHERE TB_ITEM_ORC.ID_ACAO_PARC IN (SELECT TB_ACAO_PARC.ID_ACAO_PARC FROM TB_ACAO_PARC WHERE TB_ACAO_PARC.ID_PROJETO_PARC IN (SELECT TB_PROJ_PARC.ID_PROJETO_PARC FROM TB_PROJ_PARC WHERE TB_PROJ_PARC.ID_PROJETO = NUMERO))) OR TB_MUD_ITEM_ORC.ID_ITEM_ORC IN (SELECT TB_ITEM_ORC.ID_ITEM_ORC FROM TB_ITEM_ORC WHERE TB_ITEM_ORC.ID_ACAO_PARC IN (SELECT TB_ACAO_PARC.ID_ACAO_PARC FROM TB_ACAO_PARC WHERE TB_ACAO_PARC.ID_ACAO IN (SELECT TB_ACAO.ID_ACAO FROM TB_ACAO WHERE TB_ACAO.ID_PROJETO = NUMERO))) OR TB_MUD_ITEM_ORC.ID_ACAO_PARC IN (SELECT TB_ACAO_PARC.ID_ACAO_PARC FROM TB_ACAO_PARC WHERE TB_ACAO_PARC.ID_PROJETO_PARC IN (SELECT TB_PROJ_PARC.ID_PROJETO_PARC FROM TB_PROJ_PARC WHERE TB_PROJ_PARC.ID_PROJETO = NUMERO)) OR TB_MUD_ITEM_ORC.ID_ACAO_PARC IN (SELECT TB_ACAO_PARC.ID_ACAO_PARC FROM TB_ACAO_PARC WHERE TB_ACAO_PARC.ID_ACAO IN (SELECT TB_ACAO.ID_ACAO FROM TB_ACAO WHERE TB_ACAO.ID_PROJETO = NUMERO)) OR TB_MUD_ITEM_ORC.ID_CONJ_MUD IN (SELECT TB_CONJ_MUD.ID_CONJ_MUD FROM TB_CONJ_MUD WHERE TB_CONJ_MUD.ID_PROJETO = NUMERO); DELETE TB_APR_MUD_ACAO_PAIS WHERE TB_APR_MUD_ACAO_PAIS.ID_MUD_ACAO_PAIS IN (SELECT TB_MUD_ACAO_PAIS.ID_MUD_ACAO_PAIS FROM TB_MUD_ACAO_PAIS WHERE TB_MUD_ACAO_PAIS.ID_ACAO_PAIS IN (SELECT TB_ACAO_PAIS.ID_ACAO_PAIS FROM TB_ACAO_PAIS WHERE TB_ACAO_PAIS.ID_PROJETO_PAIS IN (SELECT TB_PROJ_PAIS.ID_PROJETO_PAIS FROM TB_PROJ_PAIS WHERE TB_PROJ_PAIS.ID_PROJETO = NUMERO))) OR TB_APR_MUD_ACAO_PAIS.ID_MUD_ACAO_PAIS IN (SELECT TB_MUD_ACAO_PAIS.ID_MUD_ACAO_PAIS FROM TB_MUD_ACAO_PAIS WHERE TB_MUD_ACAO_PAIS.ID_ACAO_PAIS IN (SELECT TB_ACAO_PAIS.ID_ACAO_PAIS FROM TB_ACAO_PAIS WHERE TB_ACAO_PAIS.ID_ACAO IN (SELECT TB_ACAO.ID_ACAO FROM TB_ACAO WHERE TB_ACAO.ID_PROJETO = NUMERO))) OR TB_APR_MUD_ACAO_PAIS.ID_MUD_ACAO_PAIS IN (SELECT TB_MUD_ACAO_PAIS.ID_MUD_ACAO_PAIS FROM TB_MUD_ACAO_PAIS WHERE TB_MUD_ACAO_PAIS.ID_CONJ_MUD IN (SELECT TB_CONJ_MUD.ID_CONJ_MUD FROM TB_CONJ_MUD WHERE TB_CONJ_MUD.ID_PROJETO = NUMERO)) OR TB_APR_MUD_ACAO_PAIS.ID_MUD_ACAO_PAIS IN (SELECT TB_MUD_ACAO_PAIS.ID_MUD_ACAO_PAIS FROM TB_MUD_ACAO_PAIS WHERE TB_MUD_ACAO_PAIS.ID_PROJETO_PAIS IN (SELECT TB_PROJ_PAIS.ID_PROJETO_PAIS FROM TB_PROJ_PAIS WHERE TB_PROJ_PAIS.ID_PROJETO = NUMERO)); DELETE TB_ITEM_ORC_ENT_COAUT WHERE TB_ITEM_ORC_ENT_COAUT.ID_ITEM_ORC IN (SELECT TB_ITEM_ORC.ID_ITEM_ORC FROM TB_ITEM_ORC WHERE TB_ITEM_ORC.ID_ACAO_PARC IN (SELECT TB_ACAO_PARC.ID_ACAO_PARC FROM TB_ACAO_PARC WHERE TB_ACAO_PARC.ID_ACAO IN (SELECT TB_ACAO.ID_ACAO FROM TB_ACAO WHERE TB_ACAO.ID_PROJETO = NUMERO))) OR TB_ITEM_ORC_ENT_COAUT.ID_ITEM_ORC IN (SELECT TB_ITEM_ORC.ID_ITEM_ORC FROM TB_ITEM_ORC WHERE TB_ITEM_ORC.ID_ACAO_PARC IN (SELECT TB_ACAO_PARC.ID_ACAO_PARC FROM TB_ACAO_PARC WHERE TB_ACAO_PARC.ID_PROJETO_PARC IN (SELECT TB_PROJ_PARC.ID_PROJETO_PARC FROM TB_PROJ_PARC WHERE TB_PROJ_PARC.ID_PROJETO = NUMERO))); DELETE TB_APR_MUD_ACAO WHERE TB_APR_MUD_ACAO.ID_MUD_ACAO IN (SELECT TB_MUD_ACAO.ID_MUD_ACAO FROM TB_MUD_ACAO WHERE TB_MUD_ACAO.ID_ACAO IN (SELECT TB_ACAO.ID_ACAO FROM TB_ACAO WHERE TB_ACAO.ID_PROJETO = NUMERO)) OR TB_APR_MUD_ACAO.ID_MUD_ACAO IN (SELECT TB_MUD_ACAO.ID_MUD_ACAO FROM TB_MUD_ACAO WHERE TB_MUD_ACAO.ID_CONJ_MUD IN (SELECT TB_CONJ_MUD.ID_CONJ_MUD FROM TB_CONJ_MUD WHERE TB_CONJ_MUD.ID_PROJETO = NUMERO));                                                                                                                  DELETE TB_TAREFA WHERE TB_TAREFA.ID_MARCO_CRITICO IN (SELECT TB_MARCO_CRITICO.ID_MARCO_CRITICO FROM TB_MARCO_CRITICO WHERE TB_MARCO_CRITICO.ID_ACAO IN (SELECT TB_ACAO.ID_ACAO FROM TB_ACAO WHERE TB_ACAO.ID_PROJETO = NUMERO));                                                              DELETE TB_ACAO_PAIS WHERE TB_ACAO_PAIS.ID_ACAO IN (SELECT TB_ACAO.ID_ACAO FROM TB_ACAO WHERE TB_ACAO.ID_PROJETO = NUMERO) OR TB_ACAO_PAIS.ID_PROJETO_PAIS IN (SELECT TB_PROJ_PAIS.ID_PROJETO_PAIS FROM TB_PROJ_PAIS WHERE TB_PROJ_PAIS.ID_PROJETO = NUMERO); DELETE TB_ACAO_PART WHERE TB_ACAO_PART.ID_ACAO IN (SELECT TB_ACAO.ID_ACAO FROM TB_ACAO WHERE TB_ACAO.ID_PROJETO = NUMERO) OR TB_ACAO_PART.ID_PROJETO_PART IN (SELECT TB_PROJ_PART.ID_PROJETO_PART FROM TB_PROJ_PART WHERE TB_PROJ_PART.ID_PROJETO = NUMERO); DELETE TB_ANALISE_PAR_PROJETO WHERE TB_ANALISE_PAR_PROJETO.ID_PAR_PROJETO IN (SELECT TB_PAR_PROJETO.ID_PAR_PROJETO FROM TB_PAR_PROJETO WHERE TB_PAR_PROJETO.ID_CONJ_MUD IN (SELECT TB_CONJ_MUD.ID_CONJ_MUD FROM TB_CONJ_MUD WHERE TB_CONJ_MUD.ID_PROJETO = NUMERO)) OR TB_ANALISE_PAR_PROJETO.ID_PAR_PROJETO IN (SELECT TB_PAR_PROJETO.ID_PAR_PROJETO FROM TB_PAR_PROJETO WHERE TB_PAR_PROJETO.ID_PROJETO = NUMERO);                                                                                             DELETE TB_AVAL_ACAO WHERE TB_AVAL_ACAO.ID_ACAO IN (SELECT TB_ACAO.ID_ACAO FROM TB_ACAO WHERE TB_ACAO.ID_PROJETO = NUMERO);                                       DELETE TB_CONJ_APR_MUD WHERE TB_CONJ_APR_MUD.ID_CONJ_MUD IN (SELECT TB_CONJ_MUD.ID_CONJ_MUD FROM TB_CONJ_MUD WHERE TB_CONJ_MUD.ID_PROJETO = NUMERO);                                                                                          DELETE TB_EVENTO WHERE TB_EVENTO.ID_ACAO IN (SELECT TB_ACAO.ID_ACAO FROM TB_ACAO WHERE TB_ACAO.ID_PROJETO = NUMERO);                                                       DELETE TB_ITEM_MUD WHERE TB_ITEM_MUD.ID_CONJ_MUD IN (SELECT TB_CONJ_MUD.ID_CONJ_MUD FROM TB_CONJ_MUD WHERE TB_CONJ_MUD.ID_PROJETO = NUMERO);                                                                                                              DELETE TB_PAR_PROJETO WHERE TB_PAR_PROJETO.ID_CONJ_MUD IN (SELECT TB_CONJ_MUD.ID_CONJ_MUD FROM TB_CONJ_MUD WHERE TB_CONJ_MUD.ID_PROJETO = NUMERO) AND ID_PROJETO = NUMERO; DELETE TB_PREST_CONTA WHERE TB_PREST_CONTA.ID_PROJETO_PARC IN (SELECT TB_PROJ_PARC.ID_PROJETO_PARC FROM TB_PROJ_PARC WHERE TB_PROJ_PARC.ID_PROJETO = NUMERO);                                                                                                                      DELETE TB_PROJ_PARTICIP_SET_SECEX WHERE TB_PROJ_PARTICIP_SET_SECEX.ID_PROJETO_PART IN (SELECT TB_PROJ_PART.ID_PROJETO_PART FROM TB_PROJ_PART WHERE TB_PROJ_PART.ID_PROJETO = NUMERO);                                                                             DELETE TB_ACAO WHERE ID_PROJETO = NUMERO;      DELETE TB_PROJ_PART WHERE ID_PROJETO = NUMERO;      DELETE TB_PROJ_ENT_COA WHERE ID_PROJETO = NUMERO; DELETE TB_PROJ_OBJ_ESTRAT WHERE ID_PROJETO = NUMERO; DELETE TB_PROJ_PAIS WHERE ID_PROJETO = NUMERO; DELETE TB_PROJ_PAPEL WHERE ID_PROJETO = NUMERO; DELETE TB_PROJ_PARC WHERE ID_PROJETO = NUMERO; DELETE TB_PROJ_FASE WHERE ID_PROJETO = NUMERO; DELETE TB_PROJ_PARC WHERE ID_PROJETO = NUMERO; DELETE FROM TB_PROJETO WHERE ID_PROJETO = NUMERO;END;Para concluir, DROP em todas as tabelas temporárias:DROP TABLE TB_ADM_NIVEL_1;DROP TABLE TB_ADM_NIVEL_2;DROP TABLE TB_ADM_NIVEL_3;DROP TABLE TB_ADM_NIVEL_4;DROP TABLE TB_SCRIPT_DEL_PROJETO;Mas atenção: É importante lembrar que só foi possível a criação destas queries porque foi adotado um padrão bem definido com relação à nomenclatura das tabelas, primary keys, foreign keis e nomes dos campos. Onde todas tabelas começam por "TB_", PKs por "PK_", todas as FKs por "FK_", campos identificadores por "ID_" e etc.Nesta hora percebi o quanto valeu perder bastante tempo com a definição desta modelagem.