Como uso a exclusão em cascata com o SQL Server?

332

Eu tenho 2 tabelas: T1 e T2, são tabelas existentes com dados. Temos uma relação de um para muitos entre T1 e T2. Como altero as definições da tabela para executar a exclusão em cascata no SQL Server quando um registro de T1 é excluído, todos os registros associados em T2 também são excluídos.

A restrição externa existe entre eles. Não quero descartar as tabelas ou criar um gatilho para excluir o T2. Por exemplo, quando eu excluo um funcionário, todo o registro de revisão também deve desaparecer.

T1 - Empregado,

Employee ID      
Name
Status

T2 - Revisões de Desempenho,

Employee ID - 2009 Review
Employee ID - 2010 Review
Bichvan Nguyen
fonte

Respostas:

362

Você vai precisar,

  • Solte a restrição de chave estrangeira existente,
  • Adicione um novo com a ON DELETE CASCADEconfiguração ativada.

Algo como:

ALTER TABLE dbo.T2
   DROP CONSTRAINT FK_T1_T2   -- or whatever it's called

ALTER TABLE dbo.T2
   ADD CONSTRAINT FK_T1_T2_Cascade
   FOREIGN KEY (EmployeeID) REFERENCES dbo.T1(EmployeeID) ON DELETE CASCADE
marc_s
fonte
3
Minha equipe e eu acabamos de fazer isso. Tivemos que derrubar nossas restrições e adicioná-las novamente. Isso funcionou para nós.
Daniel L. VanDenBosch
2
Como isso é a favor de uma exclusão definitiva? Uma exclusão suave nunca teria um problema de restrição. Parece exatamente o oposto de mim.
Maxx
2
@ Maxx Na exclusão física, você exclui um registro e não precisa se preocupar com registros órfãos, enquanto na exclusão virtual é necessário fazê-lo manualmente.
Ronaldo Araújo Alves
319

Para adicionar "exclusão em cascata" a uma chave estrangeira existente no SQL Server Management Studio:

Primeiro, selecione sua chave estrangeira e abra-a "DROP and Create To .." em uma nova janela de consulta.

insira a descrição da imagem aqui

Em seguida, basta adicionar ON DELETE CASCADEao ADD CONSTRAINTcomando:

n E clique no botão "Executar" para executar esta consulta.

A propósito, para obter uma lista de suas Chaves Estrangeiras e ver quais estão com a "exclusão em cascata" ativada, você pode executar este script:

SELECT 
   OBJECT_NAME(f.parent_object_id) AS 'Table name',
   COL_NAME(fc.parent_object_id,fc.parent_column_id) AS 'Field name',
   delete_referential_action_desc AS 'On Delete'
FROM sys.foreign_keys AS f,
     sys.foreign_key_columns AS fc,
     sys.tables t 
WHERE f.OBJECT_ID = fc.constraint_object_id
AND t.OBJECT_ID = fc.referenced_object_id
ORDER BY 1

E se você achar que não pode DROPuma tabela específica devido a uma restrição de chave estrangeira, mas não consegue descobrir qual FK está causando o problema, pode executar este comando:

sp_help 'TableName'

O SQL nesse artigo lista todos os FKs que fazem referência a uma tabela específica.

Espero que tudo isso ajude.

Desculpas pelo dedo comprido. Eu só estava tentando fazer um argumento.

Mike Gledhill
fonte
163

Você pode fazer isso com o SQL Server Management Studio.

→ Clique com o botão direito do mouse no design da tabela e vá para Relacionamentos e escolha a chave estrangeira no painel esquerdo e no painel direito, expanda o menu "Especificação de INSERÇÃO e ATUALIZAÇÃO" e selecione "Cascata" como regra de exclusão.

SQL Server Management Studio

Palanikumar
fonte
oi, qual é a diferença entre os 4, ativar a cascata facilita a exclusão de todos os dados em uma tabela. Como posso ver todas as teclas / fk dependências sobre esta tabela, não a partir desta tabela. Mesmo depois de excluir todos os
FKs
@aggie - Você pode verificar as dependências clicando com o botão direito do mouse na tabela -> "Exibir dependências". Além disso, o sql server fornecerá o erro detalhado com o nome da tabela e o nome da coluna como este "A instrução DELETE entrou em conflito com a restrição REFERENCE" FK_Child1_Parent1 ". O conflito ocorreu no banco de dados "TESTDB", tabela "dbo.Child1", coluna 'Parent1ID'. "
Palanikumar
@aggie - Também o quarto caso "Definir padrão" é: você deve definir a restrição padrão na coluna Chave estrangeira. Quando excluirmos o pai, o valor padrão será substituído nas tabelas filho. (Nota: o valor padrão deve corresponder à tabela pai.) Para obter mais informações, visite mssqltips.com/sqlservertip/2365/…
Palanikumar
Isso é muito útil. Eu me pergunto, por que não existe uma regra de inserção? Em outras palavras, quando adiciono uma linha ao T1, desejo que a entrada correspondente no T2 seja criada automaticamente.
Robert M.
@RobertM. Porque isso não faz sentido. Como saberia quais valores INSERIR? Você pode usar os gatilhos INSERT para gerar as linhas filhas, tente pesquisar isso.
precisa saber é o seguinte
47

Use algo como

ALTER TABLE T2
ADD CONSTRAINT fk_employee
FOREIGN KEY (employeeID)
REFERENCES T1 (employeeID)
ON DELETE CASCADE;

Preencha os nomes de coluna corretos e você deve estar definido. Como mark_s afirmou corretamente, se você já possui uma restrição de chave estrangeira, talvez seja necessário excluir primeiro a antiga e depois criar a nova.

Hyperboreus
fonte
41
@marc_s - na verdade, você pode adicionar uma segunda chave estrangeira exatamente às mesmas colunas dos dois lados, e ela funcionará corretamente. Se estiver trabalhando em um ambiente de produção sem tempo de inatividade, talvez seja preferível introduzir o novo FK com cascata e soltar o FK mais antigo, em vez de deixar uma janela na mesa quando nenhum FK estiver no lugar. (Apenas testado em SQL 2008)
Damien_The_Unbeliever
Isto está certo. Eu tentei isso e funciona. Não há necessidade de eliminar as primeiras restrições de chave estrangeira. Obrigado pela resposta.
Bichvan Nguyen
15

Primeiro a ativar a propriedade ONCascade:

1.Drop a restrição de chave estrangeira existente

2. adicione um novo com a configuração ON DELETE CASCADE ativada

Ex:

IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.Response'))
 BEGIN 

ALTER TABLE [dbo].[Response] DROP CONSTRAINT [FK_Response_Request]  

ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

ELSE

 BEGIN 
 ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

Segundo para desativar a propriedade ONCascade:

1.Drop a restrição de chave estrangeira existente

2. Adicione um novo com a configuração ON DELETE NO ACTION ativada

Ex:

IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.Response'))
 BEGIN 
ALTER TABLE [dbo].[Response] DROP CONSTRAINT [FK_Response_Request]  

ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

ELSE

 BEGIN 
 ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE NO ACTION 
END
ravula sandeep
fonte
15

ON DELETE CASCADE
Especifica que os dados filho são excluídos quando os dados pai são excluídos.

CREATE TABLE products
( product_id INT PRIMARY KEY,
  product_name VARCHAR(50) NOT NULL,
  category VARCHAR(25)
);

CREATE TABLE inventory
( inventory_id INT PRIMARY KEY,
  product_id INT NOT NULL,
  quantity INT,
  min_level INT,
  max_level INT,
  CONSTRAINT fk_inv_product_id
    FOREIGN KEY (product_id)
    REFERENCES products (product_id)
    ON DELETE CASCADE
);

Para essa chave estrangeira, especificamos a ON DELETE CASCADEcláusula que informa ao SQL Server para excluir os registros correspondentes na tabela filho quando os dados na tabela pai são excluídos. Portanto, neste exemplo, se um valor de product_id for excluído da tabela de produtos, os registros correspondentes na tabela de inventário que usam esse product_id também serão excluídos.

Md Shahriar
fonte
-2

Se o relacionamento de um para muitos for de T1 a T2, ele não representa uma função e, portanto, não pode ser usado para deduzir ou inferir uma função inversa que garanta que o valor T2 resultante não omita as tuplas da junção T1 que são dedutivamente válidas. , porque não há função inversa dedutivamente válida. (representar funções era o objetivo das chaves primárias.) A resposta no SQL acha que sim, você pode fazê-lo. A resposta no pensamento relacional é não, você não pode fazê-lo. Veja pontos de ambiguidade no Codd 1970. O relacionamento deveria ser muitos-para-um de T1 a T2.

frank e
fonte
-10

Eu acho que você não pode simplesmente excluir a propriedade de tabelas, e se esses forem dados de produção reais, basta excluir o conteúdo que não afeta o esquema da tabela.

Amante da maçã
fonte