207

I have a foreign key constraint in my table, I want to add ON DELETE CASCADE to it.

I have tried this:

alter table child_table_name
  modify constraint fk_name
  foreign key (child_column_name)
  references parent_table_name (parent_column_name) on delete cascade;

Doesn't work.

EDIT:
Foreign key already exists, there are data in foreign key column.

The error message I get after executing the statement:

ORA-02275: such a referential constraint already exists in the table
Ula Krukar
  • 12,549
  • 20
  • 51
  • 65

12 Answers12

230

You can not add ON DELETE CASCADE to an already existing constraint. You will have to drop and re-create the constraint. The documentation shows that the MODIFY CONSTRAINT clause can only modify the state of a constraint (i-e: ENABLED/DISABLED...).

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Vincent Malgrat
  • 66,725
  • 9
  • 119
  • 171
  • 52
    It would be helpful if this answer described how it was done rather than point to documentation. – kojow7 Dec 10 '20 at 15:40
162

First drop your foreign key and try your above command, put add constraint instead of modify constraint. Now this is the command:

ALTER TABLE child_table_name 
  ADD CONSTRAINT fk_name 
  FOREIGN KEY (child_column_name) 
  REFERENCES parent_table_name(parent_column_name) 
  ON DELETE CASCADE;
David Silva-Barrera
  • 1,006
  • 8
  • 12
pradeep
  • 1,631
  • 1
  • 10
  • 2
59

As explained before:

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;

As you can see those have to be separated commands, first dropping then adding.

J.Grim
  • 11
  • 3
David Silva-Barrera
  • 1,006
  • 8
  • 12
  • This is invalid for Oracle –  Jan 01 '17 at 14:49
  • Just tested in SqlServer, but possible you have to chance `go` with semi-colon as in postgres and SqlServer itself. But the remain core codes are sql standar. Test with semi-colons, I just changed it – David Silva-Barrera Jan 03 '17 at 14:42
  • The `[` or `]` are invalid in standard SQL (and Oracle). Oracle also does not support `on update` clause for a foreign key. –  Jan 03 '17 at 14:44
  • You're right, `[` `]` are SqlServer specific. I'll clean it out more. About `on update` I can't say anything about. – David Silva-Barrera Jan 03 '17 at 14:47
28

Answer for MYSQL USERS:

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;
Adrian W
  • 4,563
  • 11
  • 38
  • 52
bhavani
  • 281
  • 3
  • 2
  • 1
    Welcome to StackOverflow. Please learn about formatting code in https://stackoverflow.com/editing-help. I edited the code for you to make it more readable. – Adrian W Aug 08 '18 at 19:05
12

This PL*SQL will write to DBMS_OUTPUT a script that will drop each constraint that does not have delete cascade and recreate it with delete cascade.

NOTE: running the output of this script is AT YOUR OWN RISK. Best to read over the resulting script and edit it before executing it.

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
  • 1,267
  • 15
  • 29
10

Here is an handy solution! I'm using SQL Server 2008 R2.

As you want to modify the FK constraint by adding ON DELETE/UPDATE CASCADE, follow these steps:

NUMBER 1:

Right click on the constraint and click to Modify

enter image description here

NUMBER 2:

Choose your constraint on the left side (if there are more than one). Then on the right side, collapse "INSERT And UPDATE Specification" point and specify the actions on Delete Rule or Update Rule row to suit your need. After that, close the dialog box.

enter image description here

NUMBER 3:

The final step is to save theses modifications (of course!)

enter image description here

PS: It's saved me from a bunch of work as I want to modify a primary key referenced in another table.

Serge Kishiko
  • 466
  • 1
  • 6
  • 13
7

For anyone using MySQL:

If you head into your PHPMYADMIN webpage and navigate to the table that has the foreign key you want to update, all you have to do is click the Relational view located in the Structure tab and change the On delete select menu option to Cascade.

Image shown below:

enter image description here

Community
  • 1
  • 1
James111
  • 15,378
  • 15
  • 78
  • 121
  • OP is from 2009, its Oracle question tagged, and PHPMYADMIN is a third-party software component for MySQL. – vegatripy Sep 23 '15 at 10:55
  • 8
    Absolutely true. But I Googled for this question, wanting to know how to do this in MySQL, and Google brought me here. Yes, the question is tagged with Oracle, so this answer isn't correct... but it will be useful to readers like myself who stumble across this Answer. So it *does* add value to this page, even if it isn't Oracle specific. So, thank you James111 ! – Mike Gledhill Mar 09 '16 at 08:07
  • Also, a bonus for this method is that PHPMYADMIN does the hard work. You don't have to delete the constraint first. Make sure the table is INNODB. – Sablefoste Feb 09 '22 at 02:31
  • Useful answer. from PHPmyAdmin is possible to see the SQL code and learn from it – Jordao Manguena Apr 08 '23 at 18:34
4

If you want to change a foreign key without dropping it you can do:

ALTER TABLE child_table_name  WITH CHECK ADD FOREIGN KEY(child_column_name)
REFERENCES parent_table_name (parent_column_name) ON DELETE CASCADE
RedPelle
  • 285
  • 4
  • 17
3

for postgresql

BEGIN TRANSACTION ;
ALTER TABLE bank_accounts
    DROP CONSTRAINT bank_accounts_company_id_fkey;

ALTER TABLE bank_accounts
    ADD CONSTRAINT bank_accounts_company_id_fkey FOREIGN KEY (company_id)
        REFERENCES companies (id)
        ON DELETE CASCADE;
END;
Ryabchenko Alexander
  • 10,057
  • 7
  • 56
  • 88
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
  • 2,439
  • 29
  • 32
0

Also good idea is to use transaction

begin transaction;
    alter table  child_table_name  drop constraint fk_name;
    alter table child_table_name add constraint fk_name
            foreign key (child_column_name)  
            references parent_table_name (parent_column_name)  on delete cascade;
end;
Ryabchenko Alexander
  • 10,057
  • 7
  • 56
  • 88
  • 1
    While possibly correct, a code-only answer helps the person who asked the question, it doesn't do them or future visitors any good. See [Is there any benefit in code-only answers?](https://meta.stackexchange.com/a/148274/183937) – Rohit Gupta Apr 23 '23 at 03:56
-1

MySQL workbench img Right click at the table you want to alter and click alter table, then click Foreign Keys. You can see Foreign Keys Options on the right side and just select cascade and click apply!