Как добавить "on DELETE CASCADE" в инструкцию ALTER TABLE

у меня есть ограничение внешнего ключа в моей таблице, я хочу добавить к нему DELETE CASCADE.

Я попытался это:

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

не работает.

EDIT:
Внешний ключ уже существует, есть данные в столбце внешнего ключа.

сообщение об ошибке я получаю после выполнения инструкции:

ORA-02275: such a referential constraint already exists in the table

8 ответов


вы не можете добавить ON DELETE CASCADE к уже существующему ограничению. Вам придется drop и re -create ограничения. The документация видно, что MODIFY CONSTRAINT предложение может изменять только государственные ограничения (i-e:ENABLED/DISABLED...).


первый drop ваш внешний ключ и попробуйте свою команду выше, put 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;

этот PL * SQL будет записывать в DBMS_OUTPUT скрипт, который удалит каждое ограничение, которое не имеет delete cascade, и воссоздаст его с помощью delete cascade.

Примечание: запуск вывода этого скрипта на свой страх и риск. Лучше всего прочитать полученный скрипт и отредактировать его перед выполнением.

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;

Как уже было сказано:

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;

Как вы можете видеть, они должны быть разделены командами, сначала отбрасывая, а затем добавляя.


для тех, кто использует MySQL:

если вы направляетесь в свой PHPMYADMIN веб-страницу и перейдите в таблицу, которая имеет внешний ключ, который вы хотите обновить, все, что вам нужно сделать, это нажать Relational view расположенном в Structure tab и изменить On delete выберите пункт Cascade.

изображение показано ниже:

enter image description here


вот удобное решение! Я использую SQL Server 2008 R2.

Если вы хотите изменить ограничение FK, добавив каскад удаления/обновления, выполните следующие действия:

номер 1:

щелкните правой кнопкой мыши на ограничении и выберите изменить

enter image description here

номер 2:

выберите ограничение с левой стороны (если их несколько). Затем на правой стороне, свернуть "спецификация вставки и обновления" укажите и укажите действия по удалению правила или обновлению строки правила в соответствии с вашими потребностями. После этого закройте диалоговое окно.

enter image description here

номер 3:

последним шагом является сохранение изменений тезисов (конечно!)

enter image description here

PS: это спасло меня от кучи работы, поскольку я хочу изменить первичный ключ, на который ссылается другой таблица.


Если вы хотите изменить внешний ключ, не опуская его, вы можете сделать:

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

ответ для пользователей 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;