如何在ALTER TABLE语句中添加“ ON DELETE CASCADE”


130

我的表中有一个外键约束,我想向其添加ON DELETE CASCADE。

我已经试过了:

修改表child_table_name
  修改约束fk_name
  外键(child_column_name)
  在删除级联上引用parent_table_name(parent_column_name);

不起作用

编辑:
外键已经存在,外键列中有数据。

执行该语句后收到的错误消息:

ORA-02275:此类引用约束已存在于表中

有什么问题?该语句被拒绝,删除不会发生..
Thorsten

Answers:



86

首先,drop您的外键并尝试使用上述命令,add constraint而不是modify constraint。现在这是命令:

ALTER TABLE child_table_name 
  ADD CONSTRAINT fk_name 
  FOREIGN KEY (child_column_name) 
  REFERENCES parent_table_name(parent_column_name) 
  ON DELETE CASCADE;

24
他为我们提供了完整的代码,这对于与postgres无关的人来说无疑是一个优势
Matthis Kohli 2015年

1
@WiiMaxx创始人嫉妒的家伙。笑这个答案比第一个答案更重要,因为这也提供代码..
我是最愚蠢的人

11

该PL * SQL将向DBMS_OUTPUT写入脚本,该脚本将删除每个没有删除级联的约束,并使用删除级联重新创建它。

注意:运行此脚本的输出的风险由您自己承担。最好在执行脚本之前先阅读生成的脚本并对其进行编辑。

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;

11

如前所述:

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;

如您所见,那些必须分开的命令,首先删除然后添加。


这对Oracle无效
a_horse_with_no_name

刚刚在SqlServer中进行了测试,但可能需要go使用冒号,例如postgres和SqlServer本身。但是剩下的核心代码是sql standar。使用分号进行测试,我只是更改了它
David Silva-Barrera

[]无效的标准SQL(和Oracle)。Oracle也不支持 on update外键子句。
a_horse_with_no_name

没错,[ ]是特定于SqlServer的。我会清理更多。关于on update我无话可说。
David Silva-Barrera

11

回答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;

欢迎使用StackOverflow。请在stackoverflow.com/editing-help中了解有关格式化代码的信息。我为您编辑了代码,以使其更具可读性。
阿德里安W

3

对于使用MySQL的任何人:

如果你的头到你的PHPMYADMIN网页,并导航到具有要更新外键,所有你所要做的就是点击表Relational view 地处Structure选项卡并更改On delete选择菜单选项Cascade

如下图所示:

在此处输入图片说明


OP发行于2009年,带有Oracle问题,PHPMYADMIN是MySQL的第三方软件组件。
vegatripy 2015年

7
千真万确。但是我用谷歌搜索了这个问题,想知道如何在MySQL中做到这一点,谷歌把我带到了这里。是的,这个问题被Oracle标记了,所以这个答案是不正确的……但是对于像我这样偶然发现此答案的读者来说,它将很有用。因此,即使它不是特定于Oracle的,它也确实可以为该页面增加价值。所以,谢谢James111!
Mike Gledhill

3

这是一个方便的解决方案!我正在使用SQL Server 2008 R2。

当您想通过添加ON DELETE / UPDATE CASCADE来修改FK约束时,请按照下列步骤操作:

1号:

右键单击约束,然后单击“ 修改”

在此处输入图片说明

2号:

在左侧选择约束(如果有多个约束)。然后在右侧折叠“ INSERT And UPDATE Specification ”点,并在“删除规则”或“更新规则”行上指定适合您需要的操作。之后,关闭对话框。

在此处输入图片说明

第3个:

最后一步是保存这些修改(当然!)

在此处输入图片说明

PS:由于我想修改另一个表中引用的主键,因此使我免于繁琐的工作。


完美,正是我所需要的!
Wildview

1

如果要更改外键而不删除它,可以执行以下操作:

ALTER TABLE child_table_name  WITH CHECK ADD FOREIGN KEY(child_column_name)
REFERENCES parent_table_name (parent_column_name) ON DELETE CASCADE

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.