Comment ajouter 'ON DELETE CASCADE' dans l'instruction ALTER TABLE

130

J'ai une contrainte de clé étrangère dans ma table, je veux y ajouter ON DELETE CASCADE.

J'ai essayé ceci:

alter table nom_table_enfant
  modifier la contrainte fk_name
  clé étrangère (child_column_name)
  référence nom_table_parent (nom_colonne_parent) lors de la suppression en cascade;

Ça ne marche pas.

EDIT:
la clé étrangère existe déjà, il y a des données dans la colonne de clé étrangère.

Le message d'erreur que je reçois après l'exécution de l'instruction:

ORA-02275: une telle contrainte référentielle existe déjà dans le tableau
Ula Krukar
la source
Quel est le problème? La déclaration est rejetée, la suppression ne se produit pas ..
Thorsten

Réponses:

162

Vous ne pouvez pas ajouter ON DELETE CASCADEà une contrainte déjà existante. Vous devrez dropet refaire createla contrainte. La documentation montre que la MODIFY CONSTRAINTclause ne peut modifier que l' état d'une contrainte (ie: ENABLED/DISABLED...).

Vincent Malgrat
la source
86

D'abord dropvotre clé étrangère et essayez votre commande ci-dessus, mettez à la add constraintplace de modify constraint. Voici maintenant la commande:

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
la source
24
Il nous donne tout le code c'est évidemment un avantage pour les gens qui n'ont rien à voir avec les postgres
Matthis Kohli
1
@WiiMaxx Fondateur, un gars jaloux. lol Cette réponse est plus importante que la première réponse car elle fournit également le code ..
Je suis la personne la plus stupide
11

Ce PL * SQL écrira dans DBMS_OUTPUT un script qui supprimera chaque contrainte qui n'a pas de cascade de suppression et la recréera avec une cascade de suppression.

REMARQUE: l'exécution de la sortie de ce script est À VOS PROPRES RISQUES. Il est préférable de lire le script résultant et de le modifier avant de l'exécuter.

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
la source
11

Comme expliqué précédemment:

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;

Comme vous pouvez le voir, ces commandes doivent être séparées, d'abord en les déposant puis en les ajoutant.

David Silva-Barrera
la source
Ceci n'est pas valide pour Oracle
a_horse_with_no_name
Juste testé dans SqlServer, mais possible que vous ayez le hasard goavec le point-virgule comme dans postgres et SqlServer lui-même. Mais les codes de base restants sont standard sql. Test avec des points-virgules, je viens de le changer
David Silva-Barrera
Les [ou ne ]sont pas valides dans SQL standard (et Oracle). Oracle ne prend pas non plus en charge la on updateclause pour une clé étrangère.
a_horse_with_no_name
Vous avez raison, [ ]sont spécifiques à SqlServer. Je vais le nettoyer davantage. À propos de on updateje ne peux rien dire.
David Silva-Barrera
11

Réponse pour les UTILISATEURS 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
la source
Bienvenue dans StackOverflow. Veuillez en savoir plus sur le formatage du code sur stackoverflow.com/editing-help . J'ai édité le code pour vous afin de le rendre plus lisible.
Adrian W
3

Pour toute personne utilisant MySQL:

Si vous accédez à votre PHPMYADMINpage Web et accédez à la table contenant la clé étrangère que vous souhaitez mettre à jour, tout ce que vous avez à faire est de cliquer Relational view sur l' Structureonglet situé dans l' onglet et de modifier l' On deleteoption de menu de sélection en Cascade.

Image ci-dessous:

entrez la description de l'image ici

James111
la source
OP date de 2009, sa question Oracle est étiquetée, et PHPMYADMIN est un composant logiciel tiers pour MySQL.
vegatripy
7
Absolument vrai. Mais j'ai cherché cette question sur Google, voulant savoir comment faire cela dans MySQL, et Google m'a amené ici. Oui, la question est étiquetée avec Oracle, donc cette réponse n'est pas correcte ... mais elle sera utile aux lecteurs comme moi qui tombent sur cette réponse. Donc , il n'ajouter de la valeur à cette page, même si elle n'est pas spécifique Oracle. Alors, merci James111!
Mike Gledhill
3

Voici une solution pratique! J'utilise SQL Server 2008 R2.

Comme vous souhaitez modifier la contrainte FK en ajoutant ON DELETE / UPDATE CASCADE, procédez comme suit:

NUMÉRO 1:

Faites un clic droit sur la contrainte et cliquez pour modifier

entrez la description de l'image ici

NUMÉRO 2:

Choisissez votre contrainte sur le côté gauche (s'il y en a plusieurs). Ensuite, sur le côté droit, réduisez le point " INSERT And UPDATE Specification " et spécifiez les actions sur la ligne Supprimer la règle ou Mettre à jour la règle en fonction de vos besoins. Après cela, fermez la boîte de dialogue.

entrez la description de l'image ici

NUMÉRO 3:

La dernière étape consiste à enregistrer ces modifications (bien sûr!)

entrez la description de l'image ici

PS: Cela m'a sauvé d'un tas de travail car je veux modifier une clé primaire référencée dans une autre table.

Serge Kishiko
la source
Parfait, exactement ce dont j'avais besoin aussi!
Wildview
1

Si vous souhaitez modifier une clé étrangère sans la laisser tomber, vous pouvez faire:

ALTER TABLE child_table_name  WITH CHECK ADD FOREIGN KEY(child_column_name)
REFERENCES parent_table_name (parent_column_name) ON DELETE CASCADE
RedPelle
la source
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
la source