¿La restricción de clave externa puede causar ciclos o múltiples rutas en cascada?

Resuelto asked hace 15 años • 10 respuestas

Cuando intento agregar restricciones a mis tablas, aparece el error:

La introducción de la restricción FOREIGN KEY 'FK74988DB24B3C886' en la tabla 'Empleado' puede provocar ciclos o múltiples rutas en cascada. Especifique AL ELIMINAR SIN ACCIÓN o AL ACTUALIZAR SIN ACCIÓN, o modifique otras restricciones de CLAVE EXTRANJERA.

Mi restricción está entre una Codemesa y una employeemesa. La Codetabla contiene Id, Name, FriendlyNamey Typea Value. Tiene employeeuna serie de campos que hacen referencia a códigos, de modo que pueda haber una referencia para cada tipo de código.

¿Cómo puedo configurar los campos como nulos si se elimina el código al que se hace referencia?

 avatar May 12 '09 14:05
Aceptado

SQL Server hace un recuento simple de rutas en cascada y, en lugar de intentar determinar si realmente existen ciclos, asume lo peor y se niega a crear las acciones referenciales (CASCADE): aún puede y debe crear las restricciones sin las acciones referenciales. Si no puede modificar su diseño (o hacerlo comprometería las cosas), entonces debería considerar el uso de activadores como último recurso.

La resolución de rutas en cascada por parte de FWIW es un problema complejo. Otros productos SQL simplemente ignorarán el problema y le permitirán crear ciclos, en cuyo caso será una carrera para ver cuál sobrescribirá el valor en último lugar, probablemente por ignorancia del diseñador (por ejemplo, ACE/Jet hace esto). Entiendo que algunos productos SQL intentarán resolver casos simples. El hecho es que SQL Server ni siquiera lo intenta, lo hace ultra seguro al no permitir más de una ruta y al menos así te lo dice.

Los propios Microsoft recomiendan el uso de activadores en lugar de restricciones FK.

onedaywhen avatar May 12 '2009 10:05 onedaywhen

Una situación típica con múltiples rutas en cascada será la siguiente: una tabla maestra con dos detalles, digamos "Maestro", "Detalle1" y "Detalle2". Ambos detalles se eliminan en cascada. Hasta ahora no hay problemas. Pero, ¿qué pasa si ambos detalles tienen una relación de uno a muchos con alguna otra tabla (digamos "AlgunaOtraTabla"). SomeOtherTable tiene una columna Detail1ID Y una columna Detail2ID.

Master { ID, masterfields }

Detail1 { ID, MasterID, detail1fields }

Detail2 { ID, MasterID, detail2fields }

SomeOtherTable {ID, Detail1ID, Detail2ID, someothertablefields }

En otras palabras: algunos de los registros en SomeOtherTable están vinculados con registros Detail1 y algunos de los registros en SomeOtherTable están vinculados con registros Detail2. Incluso si se garantiza que los registros de SomeOtherTable nunca pertenecen a ambos Detalles, ahora es imposible hacer que los registros de SomeOhterTable se eliminen en cascada para ambos detalles, porque hay múltiples rutas en cascada desde Master a SomeOtherTable (una a través de Detail1 y otra a través de Detail2). Quizás ya hayas entendido esto. Aquí hay una posible solución:

Master { ID, masterfields }

DetailMain { ID, MasterID }

Detail1 { DetailMainID, detail1fields }

Detail2 { DetailMainID, detail2fields }

SomeOtherTable {ID, DetailMainID, someothertablefields }

Todos los campos de ID son campos clave y de incremento automático. El quid está en los campos DetailMainId de las tablas de detalles. Estos campos son a la vez restricciones claves y referenciales. Ahora es posible eliminar todo en cascada eliminando únicamente los registros maestros. La desventaja es que para cada registro de detalle1 Y para cada registro de detalle2, también debe haber un registro DetalleMain (que en realidad se crea primero para obtener la identificación correcta y única).

hans riesebos avatar Aug 23 '2010 13:08 hans riesebos