Diferencia entre On Delete Cascade y On Update Cascade en mysql

45

Tengo dos tablas de MySQL base de datos- parent, child. Estoy tratando de agregar referencias de clave externa a mi tabla secundaria en función de la tabla primaria. ¿Hay alguna diferencia significativa entre ON UPDATE CASCADEyON DELETE CASCADE

My Parent Table

CREATE TABLE parent (
    id INT NOT NULL,
    PRIMARY KEY (id)
) ENGINE=INNODB;

Mi pregunta es: ¿Cuál es la diferencia entre las siguientes consultas sql?

  1. ON DELETE CASCADE

    CREATE TABLE child (
        id INT, 
        parent_id INT,
        INDEX par_ind (parent_id),
        FOREIGN KEY (parent_id) 
            REFERENCES parent(id)
            ON DELETE CASCADE
    ) ENGINE=INNODB;
    
  2. ON UPDATE CASCADE

    CREATE TABLE child (
        id INT, 
        parent_id INT,
        INDEX par_ind (parent_id),
        FOREIGN KEY (parent_id) 
            REFERENCES parent(id)
            ON UPDATE CASCADE
    ) ENGINE=INNODB;
    
  3. ON UPDATE CASCADE ON DELETE CASCADE

    CREATE TABLE child (
            id INT, 
            parent_id INT,
            INDEX par_ind (parent_id),
            FOREIGN KEY (parent_id) 
                REFERENCES parent(id)
                ON UPDATE CASCADE ON DELETE CASCADE
        ) ENGINE=INNODB;
    

¿Hay algún error en las consultas? ¿Qué significan estas consultas (1,2 y 3)? ¿Son iguales?

Lobo solitario
fuente
1
ps <nitpick> para completar, de lo que estás hablando arriba son de las declaraciones DDL (lenguaje de definición de datos) , y no consultas. Una consulta generalmente se considera DML (Lenguaje de manipulación de datos SELECCIONAR, INSERTAR, ACTUALIZAR, BORRAR) </nitpick>
Vérace
Otra ps nuevamente para completar, me preguntaba cuál era el valor predeterminado. Así que creé un niño sin actualización o eliminación. Lo que sucede entonces es que no puede actualizar ni eliminar un padre que tenga un hijo dependiente. Eso tiene mucho sentido, sin embargo, MySQL no siempre es un modelo de esa característica en particular :-)
Vérace

Respuestas:

64

Un muy buen hilo sobre este tema se encuentra aquí y también aquí . La guía definitiva para MySQL es, por supuesto, la documentación que se encuentra aquí .

En el estándar SQL 2003 hay 5 acciones referenciales diferentes:

  1. CASCADA
  2. RESTRINGIR
  3. NO ACCION
  4. SET NULL
  5. ESTABLECER PREDETERMINADO

Para responder la pregunta:

  1. CASCADA

    • ON DELETE CASCADEsignifica que si se elimina el registro principal, también se eliminan los registros secundarios. Esta no es una buena idea en mi opinión. Debe realizar un seguimiento de todos los datos que han estado en una base de datos, aunque esto se puede hacer usando TRIGGERs. (Sin embargo, vea la advertencia en los comentarios a continuación).

    • ON UPDATE CASCADEsignifica que si se cambia la clave primaria principal, el valor secundario también cambiará para reflejar eso. De nuevo en mi opinión, no es una gran idea. Si está cambiando PRIMARY KEYs con alguna regularidad (¡o incluso con alguna!), Hay algo mal con su diseño. De nuevo, vea los comentarios.

    • ON UPDATE CASCADE ON DELETE CASCADEsignifica que si usted UPDATE o DELETE el padre, el cambio se aplica en cascada al hijo. Esto es el equivalente ANDa los resultados de las dos primeras declaraciones.

  2. RESTRINGIR

    • RESTRICTsignifica que cualquier intento de eliminar y / o actualizar el padre fallará arrojando un error. Este es el comportamiento predeterminado en el caso de que una acción referencial no se especifique explícitamente.

      Para un ON DELETEo ON UPDATEque no se especifica, la acción predeterminada siempre es RESTRICT`.

  3. NO ACCION

    • NO ACTION: Del manual . Una palabra clave del SQL estándar. En MySQL, equivalente a RESTRICT. El servidor MySQL rechaza la operación de eliminación o actualización para la tabla primaria si hay un valor de clave externa relacionado en la tabla referenciada. Algunos sistemas de bases de datos tienen cheques diferidos, y NO ACTIONes un cheque diferido. En MySQL, las restricciones de clave externa se verifican de inmediato, por lo que NO ACTIONes lo mismo que RESTRICT.
  4. SET NULL

    • SET NULL- De nuevo del manual. Eliminar o actualizar la fila de la tabla primaria, y establecer la columna de clave externa o columnas de la tabla secundaria a NULL. Esta no es la mejor de las ideas en mi humilde opinión, principalmente porque no hay forma de "viajar en el tiempo", es decir, mirar hacia atrás en las tablas secundarias y asociar registros con NULLs con el registro principal relevante, CASCADEo usar TRIGGERs para llenar tablas de registro para realizar un seguimiento cambios (pero, ver comentarios).
  5. ESTABLECER PREDETERMINADO

    • SET DEFAULT. ¡Otra parte (potencialmente muy útil) del estándar SQL que MySQL no se ha molestado en implementar! Permite al desarrollador especificar un valor para establecer las columnas de clave externa en una ACTUALIZACIÓN o SUPRIMIR. InnoDB y NDB rechazarán las definiciones de tabla con una SET DEFAULTcláusula.

Como se mencionó anteriormente, debe pasar algún tiempo mirando la documentación, aquí .

Vérace
fuente
8
Me gusta su respuesta completa, pero no estoy de acuerdo con esta afirmación. "Debe realizar un seguimiento de todos los datos que han estado en una base de datos"; esto depende realmente del diseño y los propósitos de la base de datos. Por ejemplo, una definición de receta (no estoy hablando de comida, más bien como configuraciones de sistemas) cuando se elimina la definición de receta, no tiene sentido mantener a los hijos asociados de esa receta, que simplemente hincha la base de datos sin ninguna razón. También tablas de trabajo para sistemas de máquinas: ya no necesito los datos; proceso y deshazte de él. Aparte de eso, tu respuesta es fantástica.
StixO
2
similar a @StixO Me gusta esta respuesta principalmente, pero tengo que estar en desacuerdo con cambiar la clave principal. Definitivamente, hay diseños en los que esto sería una mala idea, pero cuando ingresa a una base de datos distribuida, puede ser muy deseable que las claves primarias se puedan reasignar libremente sin perder la identidad de un registro.
Garet Claborn
"Esta no es una buena idea en mi opinión. Debería realizar un seguimiento de todos los datos que alguna vez han estado en una base de datos". - No estoy seguro de entender tu punto. Si está en cascada 'al eliminar', entonces ya ha decidido que necesita eliminar algo. Si decide no eliminar nunca nada, nada caerá en cascada. Sin embargo, el beneficio de tenerlo es que en su aplicación puede estar seguro de que cuando busque un registro con una identificación extranjera, sepa que estará allí y que no habrá filas huérfanas que hinchen su base de datos si decide eliminar alguna cosa.
Jeff Ryan
La lógica aquí es bastante defectuosa en algunos lugares, y aún más en nuestro nuevo mundo GDPR. Sin embargo, estoy de acuerdo con la idea de que si las claves primarias están cambiando, podría ser una señal de que algo está mal.
Chuck Le Butt
Si está cambiando las CLAVES PRIMARIAS con regularidad (¡o incluso con alguna!), Hay algo mal con su diseño. ¿Quiere decir que ON UPDATE CASCADE cambia el valor de la clave o el nombre de la clave?
Billal Begueradj
8

Estas dos son acciones a realizar, respectivamente, cuando el registro referenciado en la tabla primaria cambia su identificación y cuando se elimina.

Si ejecuta:

UPDATE parent SET id = -1 WHERE id = 1;

Y hay al menos un registro childcon parent_id = 1, 1) fallará; en los casos 2) y 3), todos los registros con parent_id = 1 se actualizan a parent_id = -1.

Si ejecuta:

DELETE FROM parent WHERE id = 1;

Y hay al menos un registro childcon parent_id = 1, 2) fallará; en los casos 1) y 3), todos los registros con parent_id = 1se eliminan.

3) es sintácticamente correcto.

La documentación completa se puede encontrar en el manual .

jynus
fuente
6

No tengo suficiente reputación para comentar las respuestas anteriores. Así que pensé en elaborar un poco.

1) EN ELIMINAR CASCADA significa que si se elimina el registro primario, también se eliminan los registros secundarios que hacen referencia. ON UPDATE tiene como valor predeterminado RESTRICT, lo que significa que la ACTUALIZACIÓN en el registro primario fallará.

2) La acción ON DELETE por defecto es RESTRICT, lo que significa que el DELETE en el registro padre fallará. ON UPDATE CASCADE actualizará todos los registros secundarios de referencia cuando se actualice el registro primario.

3) Ver las acciones en CASCADA en 1) y 2) arriba.

Sobre el uso de ID de registros primarios como claves foráneas (en tablas secundarias): la experiencia dice a) si las ID son números de secuencia generados automáticamente, NO los use como claves foráneas. Use alguna otra clave principal única en su lugar. b) si los ID son GUID, entonces está bien usarlos como claves foráneas. Verá la sabiduría en esta sugerencia cuando exporte e importe los registros o copie registros a otra base de datos. Es demasiado engorroso lidiar con los números de secuencia generados automáticamente durante la migración de datos cuando se hace referencia a ellos como claves foráneas.

gramo
fuente