Al configurar claves externas en SQL Server, ¿en qué circunstancias debería tenerlo en cascada al eliminar o actualizar, y cuál es el razonamiento detrás de esto?
Esto probablemente también se aplica a otras bases de datos.
Estoy buscando sobre todo ejemplos concretos de cada escenario, preferiblemente de alguien que los haya usado con éxito.
sql-server
database-design
foreign-keys
rdbms
cascade
Joel Coehoorn
fuente
fuente
sql-server
etiqueta.Respuestas:
Resumen de lo que he visto hasta ahora:
Eliminar en cascada
Actualización en cascada
Cuándo usar en cascada
fuente
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 ensamblado porque no confías en la magia detrás de los compiladores.
Lo malo es el uso incorrecto de claves externas, como crearlas al revés, por ejemplo.
El ejemplo de Juan Manuel es el ejemplo canónico, si usa código hay muchas más posibilidades de dejar documentos falsos en la base de datos que vendrán y lo morderán.
Las actualizaciones en cascada son útiles, por ejemplo, cuando tiene referencias a los datos por algo que puede cambiar, digamos que una clave principal de una tabla de usuarios es la combinación de nombre y apellido. Luego, desea que los cambios en esa combinación se propaguen a donde se haga referencia.
@Aidan, esa claridad a la que te refieres tiene un alto costo, la posibilidad de dejar datos espurios en tu base de datos, que no es pequeña . Para mí, generalmente es la falta de familiaridad con el DB y la incapacidad de encontrar qué FK están en su lugar antes de trabajar con el DB lo que fomenta ese miedo. O eso, o el mal uso constante de la cascada, usándolo donde las entidades no estaban relacionadas conceptualmente, o donde tienes que preservar la historia.
fuente
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 sacar.
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 'order' y una tabla 'orderItem', es posible que desee borrar los elementos cuando elimina un orden.
Me gusta la claridad que obtengo al hacerlo en código (o procedimiento almacenado) en lugar de que ocurra 'magia'.
Por la misma razón, tampoco soy fanático de los desencadenantes.
Algo a tener en cuenta es que si elimina un 'pedido', recibirá un informe de '1 fila afectada' incluso si la eliminación en cascada ha eliminado 50 'artículos de pedido.
fuente
Trabajo mucho con eliminaciones en cascada.
Se siente bien saber que quien trabaja en contra de la base de datos nunca podría dejar datos no deseados. Si las dependencias crecen, solo cambio las restricciones en el diagrama en Management Studio y no tengo que ajustar sp o dataacces.
Dicho esto, tengo 1 problema con las eliminaciones en cascada y esas son referencias circulares. Esto a menudo conduce a partes de la base de datos que no tienen eliminaciones en cascada.
fuente
Hago mucho trabajo de base 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 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 relacionado con ellos. Me ahorra tener que escribir muchas eliminaciones complicadas que se ven desde abajo hacia arriba en mi base de datos.
No considero que las eliminaciones en cascada sean tan malas como los desencadenantes, ya que solo eliminan datos, los desencadenantes pueden tener todo tipo de cosas desagradables dentro.
En general, evito las eliminaciones reales por completo y utilizo eliminaciones lógicas (es decir, tener una columna de bits llamada isDeleted que se establece en verdadero) en su lugar.
fuente
Un ejemplo es cuando tiene dependencias entre entidades ... es decir: Documento -> DocumentItems (cuando elimina Document, DocumentItems no tiene una razón para existir)
fuente
Utilice la eliminación en cascada donde desea que se elimine el registro con el FK si se eliminó su registro PK de referencia. En otras palabras, donde 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 causar excepciones nulas.
fuente
ON Eliminar cascada:
Cuando desee que se eliminen las filas de la tabla secundaria Si la fila correspondiente se elimina en la tabla primaria.
Si no se utiliza la eliminación en cascada, se generará un error de integridad referencial .
Cascada de actualización ON:
Cuando desee que el cambio en la clave primaria se actualice en clave externa
fuente
He oído hablar de DBA y / o "Política de la empresa" que prohíbe 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 unos a otros. Tres días para recuperarse resultaron en una prohibición total de los disparadores, todo debido a las acciones de un idjit.
Por supuesto, a veces se necesitan desencadenantes en lugar de "On Delete cascade", como cuando es necesario preservar algunos datos secundarios. Pero en otros casos, es perfectamente válido usar el método en cascada On Delete. Una ventaja clave de "On Delete Cascade" es que captura TODOS los niños; un procedimiento de almacenamiento / disparo escrito personalizado puede no funcionar si no está codificado correctamente.
Creo que se debería permitir que el Desarrollador tome la decisión basándose en lo que es el desarrollo y lo que dice la especificación. Una prohibición de la alfombra basada en una mala experiencia no debería ser el criterio; el proceso de pensamiento "Nunca usar" es draconiano en el mejor de los casos. Se debe hacer una llamada de juicio cada vez, y se deben hacer cambios a medida que cambia el modelo de negocio.
¿No es esto de lo que se trata el desarrollo?
fuente
Una razón para poner 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
Caso 2: sin una eliminación en cascada
En segundo lugar, cuando agrega una tabla secundaria adicional con una eliminación en cascada, el código en el Caso 1 sigue funcionando.
Solo pondría en una cascada donde la semántica de la relación es "parte de". De lo contrario, algún idiota eliminará la mitad de su base de datos cuando lo haga:
fuente
Intento evitar eliminaciones o actualizaciones que no solicité explícitamente en el servidor SQL.
Ya sea en cascada o mediante el uso de disparadores. Tienden a morderte el culo en algún momento, ya sea al intentar localizar un error o al diagnosticar problemas de rendimiento.
Donde los usaría es para garantizar la consistencia por poco esfuerzo. Para obtener el mismo efecto, tendría que usar procedimientos almacenados.
fuente
Yo, como todos los demás aquí, encuentro que las eliminaciones en cascada son realmente solo marginalmente útiles (realmente no es mucho trabajo eliminar datos referenciados en otras tablas; si hay muchas tablas, simplemente automatizas esto con un script) pero realmente molesto cuando alguien en cascada accidentalmente elimina algunos datos importantes que son difíciles de restaurar.
El único caso en el que usaría es si los datos en la tabla 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 se ha verificado.
fuente
Una eliminación o actualización de S que elimine un valor de clave externa que se encuentra en algunas tuplas de R se puede manejar de una de estas tres maneras:
La propagación se conoce como cascada.
Hay dos casos:
‣ Si se eliminó una tupla en S, elimine las tuplas R que se refieren a ella.
‣ Si se actualizó una tupla en S, actualice el valor en las tuplas R que se refieren a ella.
fuente
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 del titular de PK o son de su propiedad. De lo contrario, todos los módulos requerirían parches inmediatos para limpiar sus elementos dependientes antes de eliminar el propietario de 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 para eliminar), después de que se haya desaconsejado la eliminación en cascada durante bastante tiempo. Tampoco es tan malo si se pierden los datos.
Sin embargo, es algo malo en las tablas de lista tipo enumeración: alguien elimina la entrada 13: amarillo de los "colores" de la tabla, y todos los elementos amarillos en la base de datos se eliminan. Además, estos a veces se actualizan de una manera delete-all-insert-all, lo que lleva a una integridad referencial totalmente omitida. Por supuesto que está mal, pero ¿cómo va a cambiar un software complejo que ha estado funcionando durante muchos años, con la introducción de una verdadera integridad referencial que corre el riesgo de sufrir efectos secundarios inesperados?
Otro problema es cuando los valores de la clave externa original se mantendrán incluso después de que se haya eliminado la clave primaria. Se puede crear una columna de lápida y una opción ON DELETE SET NULL para el FK original, pero esto nuevamente requiere disparadores o código específico para mantener el valor de clave redundante (excepto después de la eliminación de PK).
fuente
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 supertipo y subtipo para implementar físicamente supertipos / subtipos (en lugar de agrupar todos los atributos de subtipo en una sola tabla física de supertipo), hay una -una relación entre estas tablas y el problema se convierte en 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 elimina el registro de subtipo único correspondiente.
2) Asegúrese de que cualquier eliminación de un registro de subtipo también elimina el registro de supertipo. Esto se logra mediante la implementación de un desencadenador de eliminación "en lugar de" en la tabla de subtipos que va y elimina el registro de supertipo correspondiente, que, a su vez, en cascada elimina el registro de subtipo.
El uso de eliminaciones en cascada de esta manera garantiza que nunca existan registros huérfanos de supertipo o subtipo, independientemente de si elimina primero el registro de supertipo o el registro de subtipo.
fuente