terça-feira, julho 22, 2008

Delete Cascade

Já sofri por várias vezes o problema de querer apagar um tuplo e não o conseguir porque este tem uma relação com outra tabela, a qual tem um tuplo que o referencia e por isso é necessário apagar primeiro o tuplo que tem a foreign key e só depois o tuplo principal.

Vamos imaginar o seguinte cenário, tenho 3 tabelas: Form, Section e Question; estas tabelas representam formulários onde um formulário tem secções e cada secção tem questões. Para apagar um dado formulário é necessário primeiro apagar as suas secções, mas para apagar uma secção é necessário primeiro apagar as suas questões. O código seguinte possibilita-nos apagar todos os formulários cujo nome é 'xpto':

delete FROM question WHERE sectionid IN
(SELECT sectionid FROM section WHERE formid in
(SELECT formid FROM form WHERE name='xpto'));
GO

delete FROM section WHERE formid in
(SELECT formid FROM form WHERE name='xpto');
GO

delete FROM form WHERE name='xpto';
GO

Este código não é feito com objectivos de desempenho mas sim só com o único objectivo de se atingir o fim proposto que é a remoção de tuplos.

2 comentários:

Anónimo disse...

Há uma opção na criação de FKs que é ON DELETE CASCADE e que faz isso mesmo automaticamente.

Tiago Sousa disse...

Sim eu sei disso, mas muitas vezes pegas numa BD que não foi assim configurada e não podes reconfigurar porque já está numa fase de produção. E este script é exactamente a pensar nesses casos.

Além disso o on delete cascade é totalmente "descontrolado" é removido tudo cegamente, não te consigo explicar aqui por poucas palavras nem num exemplo simples, mas existem situação em que não se quer aplicar o on delete cascade porque vão ser removidas mais coisas do que realmente se quer.