Cómo agregar 'ON DELETE CASCADE' en la declaración ALTER TABLE

130

Tengo una restricción de clave externa en mi tabla, quiero agregarla EN ELIMINAR CASCADA.

He intentado esto:

alter table child_table_name
  modificar restricción nombre_fk
  clave foránea (child_column_name)
  referencias parent_table_name (parent_column_name) en delete cascade;

No funciona

EDITAR:
La clave externa ya existe, hay datos en la columna de clave externa.

El mensaje de error que recibo después de ejecutar la declaración:

ORA-02275: dicha restricción referencial ya existe en la tabla
Ula Krukar
fuente
¿Cuál es el problema? La declaración se rechaza, la eliminación no se produce ..
Thorsten

Respuestas:

162

No puede agregar ON DELETE CASCADEa una restricción ya existente. Tendrás que dropy re createla restricción. La documentación muestra que la MODIFY CONSTRAINTcláusula solo puede modificar el estado de una restricción (es decir: ENABLED/DISABLED...).

Vincent Malgrat
fuente
86

Primero dropsu clave externa y pruebe su comando anterior, ponga en add constraintlugar de modify constraint. Ahora este es el comando:

ALTER TABLE child_table_name 
  ADD CONSTRAINT fk_name 
  FOREIGN KEY (child_column_name) 
  REFERENCES parent_table_name(parent_column_name) 
  ON DELETE CASCADE;
pradeep
fuente
24
Nos da todo el código, es obvio que es una ventaja para las personas que no tienen nada que ver con postgres
Matthis Kohli
1
@WiiMaxx Fundador de un chico celoso. jajaja Esta respuesta es más importante que la primera respuesta ya que también proporciona el código ...
Soy la persona más estúpida
11

Este PL * SQL escribirá en DBMS_OUTPUT un script que eliminará cada restricción que no tenga una cascada de eliminación y la volverá a crear con la cascada de eliminación.

NOTA: ejecutar el resultado de este script es BAJO SU PROPIO RIESGO. Lo mejor es leer el guión resultante y editarlo antes de ejecutarlo.

DECLARE
      CURSOR consCols (theCons VARCHAR2, theOwner VARCHAR2) IS
        select * from user_cons_columns
            where constraint_name = theCons and owner = theOwner
            order by position;
      firstCol BOOLEAN := TRUE;
    begin
        -- For each constraint
        FOR cons IN (select * from user_constraints
            where delete_rule = 'NO ACTION'
            and constraint_name not like '%MODIFIED_BY_FK'  -- these constraints we do not want delete cascade
            and constraint_name not like '%CREATED_BY_FK'
            order by table_name)
        LOOP
            -- Drop the constraint
            DBMS_OUTPUT.PUT_LINE('ALTER TABLE ' || cons.OWNER || '.' || cons.TABLE_NAME || ' DROP CONSTRAINT ' || cons.CONSTRAINT_NAME || ';');
            -- Re-create the constraint
            DBMS_OUTPUT.PUT('ALTER TABLE ' || cons.OWNER || '.' || cons.TABLE_NAME || ' ADD CONSTRAINT ' || cons.CONSTRAINT_NAME 
                                        || ' FOREIGN KEY (');
            firstCol := TRUE;
            -- For each referencing column
            FOR consCol IN consCols(cons.CONSTRAINT_NAME, cons.OWNER)
            LOOP
                IF(firstCol) THEN
                    firstCol := FALSE;
                ELSE
                    DBMS_OUTPUT.PUT(',');
                END IF;
                DBMS_OUTPUT.PUT(consCol.COLUMN_NAME);
            END LOOP;                                    

            DBMS_OUTPUT.PUT(') REFERENCES ');

            firstCol := TRUE;
            -- For each referenced column
            FOR consCol IN consCols(cons.R_CONSTRAINT_NAME, cons.R_OWNER)
            LOOP
                IF(firstCol) THEN
                    DBMS_OUTPUT.PUT(consCol.OWNER);
                    DBMS_OUTPUT.PUT('.');
                    DBMS_OUTPUT.PUT(consCol.TABLE_NAME);        -- This seems a bit of a kluge.
                    DBMS_OUTPUT.PUT(' (');
                    firstCol := FALSE;
                ELSE
                    DBMS_OUTPUT.PUT(',');
                END IF;
                DBMS_OUTPUT.PUT(consCol.COLUMN_NAME);
            END LOOP;                                    

            DBMS_OUTPUT.PUT_LINE(')  ON DELETE CASCADE  ENABLE VALIDATE;');
        END LOOP;
    end;
shindigo
fuente
11

Como se explicó anteriormente:

ALTER TABLE TABLEName
drop CONSTRAINT FK_CONSTRAINTNAME;

ALTER TABLE TABLENAME
ADD CONSTRAINT FK_CONSTRAINTNAME
    FOREIGN KEY (FId)
    REFERENCES OTHERTABLE
        (Id)
    ON DELETE CASCADE ON UPDATE NO ACTION;

Como puede ver, esos deben ser comandos separados, primero soltar y luego agregar.

David Silva-Barrera
fuente
Esto no es válido para Oracle
a_horse_with_no_name
Acabo de probar en SqlServer, pero es posible que tengas suerte gocon punto y coma como en Postgres y SqlServer. Pero los códigos centrales restantes son estándar SQL. Prueba con punto y coma, acabo de cambiarlo
David Silva-Barrera
Los [o ]no son válidos en SQL estándar (y Oracle). Oracle tampoco admite on updatecláusula para una clave foránea.
a_horse_with_no_name
Tienes razón, [ ]son SqlServer específicos. Lo limpiaré más. Sobre on updatelo que no puedo decir nada.
David Silva-Barrera
11

Respuesta para usuarios de MySQL:

ALTER TABLE ChildTableName 
DROP FOREIGN KEY `fk_table`;
ALTER TABLE ChildTableName 
ADD CONSTRAINT `fk_t1_t2_tt`
  FOREIGN KEY (`parentTable`)
  REFERENCES parentTable (`columnName`)
  ON DELETE CASCADE
  ON UPDATE CASCADE;
Bhavani
fuente
Bienvenido a StackOverflow. Aprenda sobre el formato del código en stackoverflow.com/editing-help . Edité el código para que sea más legible.
Adrian W
3

Para cualquiera que use MySQL:

Si ingresa a su PHPMYADMINpágina web y navega a la tabla que tiene la clave externa que desea actualizar, todo lo que tiene que hacer es hacer clic en el que se Relational view encuentra en la Structurepestaña y cambiar la On deleteopción de menú de selección aCascade .

Imagen que se muestra a continuación:

ingrese la descripción de la imagen aquí

James111
fuente
OP es de 2009, su pregunta de Oracle está etiquetada, y PHPMYADMIN es un componente de software de terceros para MySQL.
vegatripy
77
Totalmente cierto. Pero busqué en Google esta pregunta, queriendo saber cómo hacer esto en MySQL, y Google me trajo aquí. Sí, la pregunta está etiquetada con Oracle, por lo que esta respuesta no es correcta ... pero será útil para los lectores como yo que se encuentran con esta respuesta. Por lo que no añaden valor a esta página, aunque no es específica de Oracle. Entonces, gracias James111!
Mike Gledhill
3

¡Aquí hay una solución práctica! Estoy usando SQL Server 2008 R2.

Como desea modificar la restricción FK agregando ON DELETE / UPDATE CASCADE, siga estos pasos:

NUMERO 1:

Haga clic derecho en la restricción y haga clic para modificar

ingrese la descripción de la imagen aquí

NÚMERO 2:

Elija su restricción en el lado izquierdo (si hay más de uno). Luego, en el lado derecho, contraiga el punto " INSERTAR Y ACTUALIZAR la especificación " y especifique las acciones en la fila Eliminar regla o Actualizar regla para satisfacer sus necesidades. Después de eso, cierre el cuadro de diálogo.

ingrese la descripción de la imagen aquí

NUMERO 3:

El último paso es guardar estas modificaciones (¡por supuesto!)

ingrese la descripción de la imagen aquí

PD: Me salvó de un montón de trabajo, ya que quiero modificar una clave principal a la que se hace referencia en otra tabla.

Serge Kishiko
fuente
¡Perfecto, exactamente lo que necesitaba también!
Wildview
1

Si desea cambiar una clave foránea sin soltarla, puede hacer lo siguiente:

ALTER TABLE child_table_name  WITH CHECK ADD FOREIGN KEY(child_column_name)
REFERENCES parent_table_name (parent_column_name) ON DELETE CASCADE
RedPelle
fuente
0
ALTER TABLE `tbl_celebrity_rows` ADD CONSTRAINT `tbl_celebrity_rows_ibfk_1` FOREIGN KEY (`celebrity_id`) 
REFERENCES `tbl_celebrities`(`id`) ON DELETE CASCADE ON UPDATE RESTRICT;
Hassan Ali Shahzad
fuente