Pregunta

Al configurar claves externas en SQL Server, ¿bajo qué circunstancias debería tenerlas en cascada al eliminarlas o actualizarlas, y cuál es el razonamiento detrás de esto?

Probablemente esto también se aplique a otras bases de datos.

Lo que más busco son ejemplos concretos de cada escenario, preferiblemente de alguien que los haya utilizado con éxito.

¿Fue útil?

Solución

Resumen de lo que he visto hasta ahora:

  • A algunas personas no les gusta nada la cascada.

Eliminación en cascada

  • La eliminación en cascada puede tener sentido cuando la semántica de la relación puede implicar una "es parte de" descripción.Por ejemplo, un registro OrderLine es parte de su pedido principal y OrderLines nunca se compartirá entre varios pedidos.Si la Orden desapareciera, la Línea de Orden también debería desaparecer, y una línea sin una Orden sería un problema.
  • El ejemplo canónico de Eliminación en cascada es SomeObject y SomeObjectItems, donde no tiene ningún sentido que exista un registro de elementos sin un registro principal correspondiente.
  • Debería no utilice Eliminación en cascada si está conservando el historial o si utiliza una "eliminación suave/lógica" en la que solo establece una columna de bits eliminados en 1/verdadero.

Actualización en cascada

  • La actualización en cascada puede tener sentido cuando se utiliza una clave real en lugar de una clave sustituta (columna de identidad/incremento automático) en todas las tablas.
  • El ejemplo canónico de Cascade Update es cuando tienes una clave externa mutable, como un nombre de usuario que se puede cambiar.
  • Debería no use Actualización en cascada con claves que sean columnas de identidad/incremento automático.
  • La actualización en cascada se utiliza mejor junto con una restricción única.

Cuándo utilizar la cascada

  • Es posible que desee obtener una confirmación más sólida del usuario antes de permitir que una operación se realice en cascada, pero depende de su aplicación.
  • La conexión en cascada puede causarle problemas si configura mal sus claves externas.Pero deberías estar bien si lo haces bien.
  • No es aconsejable utilizar la cascada antes de comprenderla a fondo.Sin embargo, es una característica útil y, por lo tanto, vale la pena tomarse el tiempo para comprenderla.

Otros consejos

Las claves externas son la mejor manera de garantizar la integridad referencial de una base de datos.Evitar las cascadas por ser mágico es como escribir todo en ensamblador porque no confías en la magia detrás de los compiladores.

Lo malo es el uso incorrecto de claves foráneas, como crearlas al revés, por ejemplo.

El ejemplo de Juan Manuel es el ejemplo canónico, si usas código hay muchas más posibilidades de dejar DocumentItems falsos en la base de datos que vendrán a morderte.

Las actualizaciones en cascada son útiles, por ejemplo, cuando tiene referencias a los datos mediante algo que puede cambiar, digamos que una clave principal de una tabla de usuarios es la combinación de nombre y apellido.Entonces desea que los cambios en esa combinación se propaguen a dondequiera que se haga referencia a ellos.

@Aidan, esa claridad a la que te refieres tiene un alto costo, la posibilidad de dejar datos falsos en tu base de datos, lo cual es no pequeño.Para mí, normalmente es simplemente la falta de familiaridad con la base de datos y la incapacidad de encontrar qué FK están implementados antes de trabajar con la base de datos lo que fomenta ese miedo.O eso, o un mal uso constante de la cascada, usándola donde las entidades no estaban relacionadas conceptualmente, o donde hay que preservar la historia.

Nunca uso eliminaciones en cascada.

Si quiero que se elimine algo de la base de datos, quiero decirle explícitamente a la base de datos lo que quiero eliminar.

Por supuesto, son una función disponible en la base de datos y puede haber ocasiones en las que esté bien usarlas, por ejemplo, si tiene una tabla de 'pedido' y una tabla de 'artículo de pedido', es posible que desee borrar los elementos cuando elimine un orden.

Me gusta la claridad que obtengo al hacerlo en código (o procedimiento almacenado) en lugar de que suceda "magia".

Por la misma razón tampoco soy fanático de los desencadenantes.

Algo a tener en cuenta es que si elimina un "pedido", obtendrá el informe "1 fila afectada" incluso si la eliminación en cascada ha eliminado 50 "artículos de pedido".

Trabajo mucho con eliminaciones en cascada.

Es bueno saber que quienquiera que trabaje en la base de datos nunca dejará datos no deseados.Si las dependencias crecen, simplemente cambio las restricciones en el diagrama en Management Studio y no tengo que modificar el sp o el acceso a los datos.

Dicho esto, tengo un problema con las eliminaciones en cascada y son las referencias circulares.Esto a menudo conduce a partes de la base de datos que no tienen eliminaciones en cascada.

Trabajo mucho en bases de datos y rara vez encuentro útiles las eliminaciones en cascada.La única vez que los he usado de manera efectiva es en una base de datos de informes que se actualiza mediante un trabajo nocturno.Me aseguro de que todos los datos modificados se importen correctamente eliminando los registros de nivel superior que hayan cambiado desde la última importación, luego vuelvo a importar los registros modificados y todo lo que se relacione con ellos.Me ahorra tener que escribir muchas eliminaciones complicadas que van desde la parte inferior hasta la parte superior de mi base de datos.

No considero que las eliminaciones en cascada sean tan malas como los activadores, ya que solo eliminan datos, los activadores pueden tener todo tipo de cosas desagradables en su interior.

En general, evito las eliminaciones reales por completo y uso eliminaciones lógicas (es decir,tener una columna de bits llamada isDeleted que se establece en verdadero) en su lugar.

Un ejemplo es cuando tienes dependencias entre entidades...es decir:Documento -> DocumentItems (cuando eliminas un documento, los DocumentItems no tienen una razón para existir)

Utilice la eliminación en cascada donde desee que se elimine el registro con el FK si se eliminó el registro PK de referencia.En otras palabras, cuando el registro no tiene sentido sin el registro de referencia.

Considero que la eliminación en cascada es útil para garantizar que las referencias muertas se eliminen de forma predeterminada en lugar de provocar excepciones nulas.

ON Eliminar cascada:

Cuando quieres filas en la tabla secundaria que se eliminarán Si se elimina la fila correspondiente en la tabla principal.

Si en eliminación en cascada no se utiliza, se generará un error para integridad referencial.

EN Cascada de actualización:

Cuando quieres cambio de clave primaria para ser actualizado en clave externa

Una razón para realizar una eliminación en cascada (en lugar de hacerlo en el código) es mejorar el rendimiento.

Caso 1:Con una eliminación en cascada

 DELETE FROM table WHERE SomeDate < 7 years ago;

Caso 2:Sin eliminación en cascada

 FOR EACH R IN (SELECT FROM table WHERE SomeDate < 7 years ago) LOOP
   DELETE FROM ChildTable WHERE tableId = R.tableId;
   DELETE FROM table WHERE tableId = R.tableid;
   /* More child tables here */
 NEXT

En segundo lugar, cuando agrega una tabla secundaria adicional con una eliminación en cascada, el código en el Caso 1 sigue funcionando.

Sólo pondría una cascada donde la semántica de la relación es "parte de".De lo contrario, algún idiota borrará la mitad de tu base de datos cuando lo hagas:

DELETE FROM CURRENCY WHERE CurrencyCode = 'USD'

He oído hablar de DBA y/o "Política de la empresa" que prohíben el uso de "On Delete Cascade" (y otros) simplemente debido a malas experiencias en el pasado.En un caso, un chico escribió tres disparadores que terminaron llamándose entre sí.Tres días para recuperarse resultaron en una prohibición total de los desencadenantes, todo debido a las acciones de un idjit.

Por supuesto, a veces se necesitan activadores en lugar de "Al eliminar en cascada", como cuando es necesario conservar algunos datos secundarios.Pero en otros casos, es perfectamente válido utilizar el método en cascada On Delete.Una ventaja clave de "Al eliminar en cascada" es que captura TODOS los elementos secundarios;un procedimiento de activación/almacenamiento escrito personalizado puede no hacerlo si no está codificado correctamente.

Creo que al desarrollador se le debería permitir tomar la decisión basándose en cuál es el desarrollo y lo que dice la especificación.Una prohibición de alfombras basada en una mala experiencia no debería ser el criterio;el proceso de pensamiento de "Nunca usar" es, en el mejor de los casos, draconiano.Es necesario tomar una decisión cada vez y realizar cambios a medida que cambia el modelo de negocio.

¿No es esto de lo que se trata el desarrollo?

Intento evitar eliminaciones o actualizaciones que no solicité explícitamente en el servidor SQL.

Ya sea mediante cascada o mediante el uso de activadores.Suelen morderte el trasero en algún momento, ya sea cuando intentan localizar un error o cuando diagnostican problemas de rendimiento.

Donde los usaría es para garantizar la coherencia sin mucho esfuerzo.Para obtener el mismo efecto, tendría que utilizar procedimientos almacenados.

Yo, como todos los demás aquí, encuentro que las eliminaciones en cascada son en realidad sólo marginalmente útiles (realmente no es mucho trabajo eliminar datos referenciados en otras tablas; si hay muchas tablas, simplemente automatiza esto con un script), pero es realmente molesto. cuando alguien elimina accidentalmente en cascada algunos datos importantes que son difíciles de restaurar.

El único caso en el que lo usaría es si los datos de la tabla están altamente controlados (por ejemplo, permisos limitados) y solo se actualizan o eliminan a través de un proceso controlado (como una actualización de software) que haya sido verificado.

Una eliminación o actualización de S que elimina un valor de clave externa que se encuentra en algunas tuplas de R se puede manejar de una de tres maneras:

  1. Rechazo
  2. Propagación
  3. anulación.

La propagación se conoce como cascada.

Hay dos casos:

‣ Si se eliminó una tupla en S, elimine las tuplas R que hacían referencia a ella.

‣ Si se actualizó una tupla en S, actualice el valor en las tuplas R que hacen referencia a ella.

Si está trabajando en un sistema con muchos módulos diferentes en diferentes versiones, puede ser muy útil si los elementos eliminados en cascada son parte o propiedad del titular de la PK.De lo contrario, todos los módulos requerirían parches inmediatos para limpiar sus elementos dependientes antes de eliminar al propietario de la PK, o la relación de clave externa se omitiría por completo, posiblemente dejando toneladas de basura en el sistema si la limpieza no se realiza correctamente.

Acabo de introducir la eliminación en cascada para una nueva tabla de intersección entre dos tablas ya existentes (solo la intersección a eliminar), después de que se había desaconsejado la eliminación en cascada durante bastante tiempo.Tampoco es tan malo si se pierden datos.

Sin embargo, es algo malo en tablas de listas tipo enumeración:alguien elimina la entrada 13 - amarillo de la tabla "colores" y todos los elementos amarillos de la base de datos se eliminan.Además, a veces estos se actualizan eliminando todo e insertando todo, lo que lleva a que se omita por completo la integridad referencial.Por supuesto que está mal, pero ¿cómo se puede cambiar un software complejo que se ha estado ejecutando durante muchos años y cuya introducción de una verdadera integridad referencial corre el riesgo de sufrir efectos secundarios inesperados?

Otro problema es cuando los valores de clave externa originales se deben conservar incluso después de que se haya eliminado la clave principal.Se puede crear una columna de desecho y una opción ON DELETE SET NULL para la FK original, pero esto nuevamente requiere activadores o código específico para mantener el valor de la clave redundante (excepto después de la eliminación de la PK).

Las eliminaciones en cascada son extremadamente útiles cuando se implementan entidades lógicas de supertipo y subtipo en una base de datos física.

Cuando se utilizan tablas separadas de supertipos y subtipos para implementar físicamente supertipos/subtipos (en lugar de agrupar todos los atributos de subtipos en una única tabla física de supertipos), existe una tabla uno a uno. -Una relación entre estas tablas y el problema es cómo mantener las claves primarias 100% sincronizadas entre estas tablas.

Las eliminaciones en cascada pueden ser una herramienta muy útil para:

1) Asegúrese de que al eliminar un registro de supertipo también se elimine el registro de subtipo único correspondiente.

2) Asegúrese de que cualquier eliminación de un registro de subtipo también elimine el registro de supertipo.Esto se logra implementando un activador de eliminación "en lugar de" en la tabla de subtipo que elimina el registro de supertipo correspondiente, lo que, a su vez, elimina en cascada el registro de subtipo.

El uso de eliminaciones en cascada de esta manera garantiza que nunca existan registros de supertipo o subtipo huérfanos, independientemente de si elimina primero el registro de supertipo o el registro de subtipo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top