Recursividade - Registro pai, filhos, netos, bisnetos...

terça-feira, 1 de dezembro de 2009

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 + filhos
CREATE GLOBAL TEMPORARY TABLE TB_ADM_NIVEL_1 AS
SELECT 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_1
FROM 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 + netos
CREATE GLOBAL TEMPORARY TABLE TB_ADM_NIVEL_2 AS
SELECT 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_2
FROM 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 + bisnetos
CREATE GLOBAL TEMPORARY TABLE TB_ADM_NIVEL_3 AS
SELECT 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_3
FROM 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 + tataranetos
CREATE GLOBAL TEMPORARY TABLE TB_ADM_NIVEL_4 AS
SELECT 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_4
FROM 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 = VAZIO
CREATE GLOBAL TEMPORARY TABLE TB_ADM_NIVEL_5 AS
SELECT 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_5
FROM 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_PROJETO
AS

-- APAGAR REGISTROS DAS TABELAS FILHAS NIVEL 4
SELECT 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 NIVEL
FROM TB_ADM_NIVEL_1 TN1, TB_ADM_NIVEL_2 TN2, TB_ADM_NIVEL_3 TN3, TB_ADM_NIVEL_4 TN4
WHERE TN1.CAMPO_FILHA_1 = TN2.CAMPO_PAI_1
AND TN2.CAMPO_FILHA_2 = TN3.CAMPO_PAI_2
AND TN3.CAMPO_FILHA_3 = TN4.CAMPO_PAI_3

UNION

-- APAGAR REGISTROS DAS TABELAS FILHAS NIVEL 3
SELECT 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 NIVEL
FROM TB_ADM_NIVEL_1 TN1, TB_ADM_NIVEL_2 TN2, TB_ADM_NIVEL_3 TN3
WHERE TN1.CAMPO_FILHA_1 = TN2.CAMPO_PAI_1
AND TN2.CAMPO_FILHA_2 = TN3.CAMPO_PAI_2

UNION

-- APAGAR REGISTROS DAS TABELAS FILHAS NIVEL 2
SELECT 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 NIVEL
FROM TB_ADM_NIVEL_1 TN1, TB_ADM_NIVEL_2 TN2
WHERE TN1.CAMPO_FILHA_1 = TN2.CAMPO_PAI_1

UNION

-- APAGAR REGISTROS DAS TABELAS FILHAS NIVEL 1 SEM FILHOS NIVEL 2
SELECT
'DELETE ' || TABELA_FILHA_1 ||
' WHERE ' || CAMPO_PAI_0 || ' = NUMERO;' AS SCRIPT, TABELA_FILHA_1 AS TABELA, 1 AS NIVEL
FROM TB_ADM_NIVEL_1
WHERE TABELA_FILHA_1 <> 'TB_PROJETO'

UNION

-- SCRIPT PARA APAGAR REGISTRO DA TABELA DE PROJETO
SELECT '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 RESULTADO
SELECT 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 AQUI
DECLARE 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.

0 comentários: