¿Cómo uso la eliminación en cascada con SQL Server?

332

Tengo 2 tablas: T1 y T2, son tablas existentes con datos. Tenemos una relación de uno a muchos entre T1 y T2. ¿Cómo modifico las definiciones de tabla para realizar la eliminación en cascada en SQL Server cuando se elimina un registro de T1, también se eliminan todos los registros asociados en T2.

La restricción externa está en su lugar entre ellos. No quiero soltar las tablas o crear un disparador para hacer la eliminación de T2. Por ejemplo, cuando elimino a un empleado, todos los registros de revisión también deberían desaparecer.

T1 - Empleado,

Employee ID      
Name
Status

T2 - Opiniones de rendimiento,

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

Respuestas:

362

Necesitaras,

  • Descarte la restricción de clave externa existente,
  • Agregue uno nuevo con la ON DELETE CASCADEconfiguración habilitada.

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
fuente
3
Mi equipo y yo acabamos de hacer esto. Tuvimos que BAJAR nuestras restricciones y volver a agregarlas. Esto funcionó para nosotros.
Daniel L. VanDenBosch
2
¿Cómo es esto a favor de una eliminación dura? Una eliminación suave nunca tendría un problema de restricción. Me parece todo lo contrario.
Maxx
2
@Maxx En el borrado completo, borra un registro y no necesita preocuparse por los registros huérfanos, mientras que en el borrado suave debe hacerlo manualmente.
Ronaldo Araújo Alves
319

Para agregar "Eliminar en cascada" a una clave externa existente en SQL Server Management Studio:

Primero, seleccione su Clave externa y abra "DROP and Create To ..." en una nueva ventana de consulta.

ingrese la descripción de la imagen aquí

Luego, solo agregue ON DELETE CASCADEal ADD CONSTRAINTcomando:

norte Y presiona el botón "Ejecutar" para ejecutar esta consulta.

Por cierto, para obtener una lista de sus claves externas y ver cuáles tienen activada la opción "Eliminar en cascada", puede ejecutar 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

Y si alguna vez encuentra que no puede DROPuna tabla en particular debido a una restricción de clave externa, pero no puede determinar qué FK está causando el problema, puede ejecutar este comando:

sp_help 'TableName'

El SQL en ese artículo enumera todos los FK que hacen referencia a una tabla en particular.

Espero que todo esto ayude.

Disculpas por el dedo largo. Solo estaba tratando de hacer un punto.

Mike Gledhill
fuente
163

Puede hacer esto con SQL Server Management Studio.

→ Haga clic con el botón derecho en el diseño de la tabla y vaya a Relaciones y elija la clave externa en el panel del lado izquierdo y en el panel del lado derecho, expanda el menú "INSERTAR y ACTUALIZAR la especificación" y seleccione "Cascada" como Eliminar regla.

SQL Server Management Studio

Palanikumar
fuente
Hola, ¿cuál es la diferencia entre los 4? Activar la cascada hace que sea fácil eliminar todos los datos de una tabla. ¿Cómo puedo ver todas las dependencias / claves fk en esta tabla, no desde esta tabla? Incluso después de eliminar todos los FK, sigo teniendo un error
aggie
@aggie - Puede verificar las dependencias haciendo clic con el botón derecho en la tabla -> "Ver dependencias". Además, el servidor SQL le dará el error detallado con el nombre de la tabla y el nombre de la columna como este "La declaración DELETE está en conflicto con la restricción REFERENCE" FK_Child1_Parent1 ". El conflicto ocurrió en la base de datos "TESTDB", tabla "dbo.Child1", columna 'Parent1ID' ".
Palanikumar
@aggie: también el 4º caso "Establecer valor predeterminado" es: debe establecer la restricción predeterminada en la columna Clave externa, cuando eliminemos el elemento primario, el valor predeterminado se reemplazará en las tablas secundarias. (Nota: el valor predeterminado debe coincidir con la tabla principal). Para obtener más información, visite mssqltips.com/sqlservertip/2365/…
Palanikumar
Esto es muy útil. Me pregunto, ¿por qué no hay una regla de inserción? En otras palabras, cuando agrego una fila a T1, quiero que la entrada correspondiente en T2 se cree automáticamente.
Robert M.
@RobertM. Porque eso no tiene sentido. ¿Cómo sabría qué valores INSERTAR? Es posible que pueda utilizar los disparadores INSERT para generar las filas secundarias, intente investigar eso.
Dan Bechard el
47

Usa algo como

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

Complete los nombres de columna correctos y debería estar configurado. Como mark_s dijo correctamente, si ya tiene una restricción de clave externa en su lugar, tal vez necesite eliminar primero la antigua y luego crear la nueva.

Hiperbóreo
fuente
41
@marc_s: en realidad, puede agregar una segunda clave externa contra exactamente las mismas columnas en ambos lados, y funcionará correctamente. Si trabaja en un entorno de producción sin tiempo de inactividad, puede ser preferible introducir el nuevo FK con cascada, y luego dejar caer el FK anterior, en lugar de dejar una ventana en la mesa cuando no hay FK en su lugar. (Acabo de probar en SQL 2008)
Damien_The_Unbeliever
Esto es correcto. Intenté esto, y funciona. No es necesario eliminar las primeras restricciones de clave externa. Gracias por la respuesta.
Bichvan Nguyen
15

Primero para habilitar la propiedad ONCascade:

1. Descarte la restricción de clave externa existente

2.añada uno nuevo con la configuración ON DELETE CASCADE habilitada

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 deshabilitar la propiedad ONCascade:

1. Descarte la restricción de clave externa existente

2.Agregue uno nuevo con el ajuste ON DELETE NO ACTION habilitado

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
fuente
15

ON DELETE CASCADE
Especifica que los datos secundarios se eliminan cuando se eliminan los datos principales.

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 esta clave externa, hemos especificado la ON DELETE CASCADEcláusula que le dice a SQL Server que elimine los registros correspondientes en la tabla secundaria cuando se eliminan los datos en la tabla primaria. Entonces, en este ejemplo, si se elimina un valor de product_id de la tabla de productos, los registros correspondientes en la tabla de inventario que usan este product_id también se eliminarán.

MD Shahriar
fuente
-2

Si la relación uno a muchos es de T1 a T2, entonces no representa una función y, por lo tanto, no se puede usar para deducir o inferir una función inversa que garantice que el valor T2 resultante no omita las tuplas de T1 unirse a T2 que son válidas deductivamente , porque no hay una función inversa deductivamente válida. (representar las funciones era el propósito de las claves primarias). La respuesta en SQL think es sí, puede hacerlo. La respuesta en el pensamiento relacional es no, no puedes hacerlo. Véanse los puntos de ambigüedad en Codd 1970. La relación debería ser de muchos a uno de T1 a T2.

Frank e
fuente
-10

Creo que no puede simplemente eliminar la propiedad de tablas, y si se trata de datos de producción reales, simplemente elimine el contenido que no afecta el esquema de la tabla.

Amante de la manzana
fuente