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

79

У меня есть ограничение внешнего ключа в моей таблице, я хочу добавить к нему 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
  • 0
    В чем проблема? Заявление отклонено, удаление не происходит ..
Теги:

5 ответов

116
Лучший ответ

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

36

Сначала 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;
  • 2
    конечно, ваш ответ правильный, но этот Вопрос от 2009 года и уже имеет ответ, который почти объясняет то же самое, так каково преимущество в вашем ответе?
  • 21
    Он дает нам весь код, это очевидно преимущество для людей, которые не имеют ничего общего с postgres
Показать ещё 2 комментария
5

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

ПРИМЕЧАНИЕ. Выполнение вывода этого script - это ВАШ СОБСТВЕННЫЙ РИСК. Лучше всего читать результирующий script и редактировать его перед его выполнением.

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;
3

Как объяснялось ранее:

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;

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

  • 0
    Это неверно для Oracle
  • 0
    Просто испытания в SqlServer, но возможно вам придется шанс go с запятой , как в Postgres и самой SqlServer. Но оставшиеся основные коды - это стандарт SQL. Тест с точкой с запятой, я просто изменил
Показать ещё 2 комментария
0

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

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

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

Изображение 7149

  • 0
    ОП с 2009 года, его вопрос Oracle помечен, а PHPMYADMIN является сторонним программным компонентом для MySQL.
  • 7
    Абсолютная правда. Но я гуглил на этот вопрос, желая узнать, как это сделать в MySQL, и Google привел меня сюда. Да, вопрос помечен Oracle, поэтому этот ответ не верен ... но он будет полезен для таких читателей, как я, которые наткнулись на этот ответ. Так что это добавляет ценность этой странице, даже если это не специфично для Oracle. Итак, спасибо James111!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню