Jak dodać „ON DELETE CASCADE” w instrukcji ALTER TABLE

133

Mam ograniczenie klucza obcego w mojej tabeli, chcę dodać do niego ON DELETE CASCADE.

Próbowałem tego:

zmiana tabeli nazwa_tabeli_podrzędnej
  zmodyfikuj ograniczenie fk_name
  klucz obcy (nazwa_kolumny_podrzędnej)
  odwołuje się nazwa_tabeli_nadrzędnej (nazwa_kolumny_nadrzędnej) przy usuwaniu kaskadowym;

Nie działa.

EDYCJA:
Klucz obcy już istnieje, w kolumnie klucza obcego znajdują się dane.

Komunikat o błędzie, który otrzymuję po wykonaniu instrukcji:

ORA-02275: takie ograniczenie referencyjne już istnieje w tabeli
Ula Krukar
źródło
Jaki jest problem? Oświadczenie zostało odrzucone, usunięcie nie następuje ...
Thorsten

Odpowiedzi:

164

Nie możesz dodać ON DELETE CASCADEdo już istniejącego ograniczenia. Będziesz musiał dropi powstrzymać createprzymus. Z dokumentacji wynika, że MODIFY CONSTRAINTklauzula może tylko modyfikować stan ograniczenia (tj .: ENABLED/DISABLED...).

Vincent Malgrat
źródło
93

Najpierw dropklucz obcy i wypróbuj powyższe polecenie, wstaw add constraintzamiast modify constraint. Teraz to jest polecenie:

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
źródło
24
Daje nam cały kod, co oczywiście jest zaletą dla osób, które nie mają nic wspólnego z postgresem
Matthis Kohli
1
Założyciel @WiiMaxx, zazdrosny facet. lol Ta odpowiedź jest ważniejsza niż pierwsza odpowiedź, ponieważ zawiera również kod ...
Jestem najbardziej głupią osobą
17

Jak wyjaśniono wcześniej:

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;

Jak widać, muszą to być oddzielne polecenia, najpierw upuszczone, a następnie dodane.

David Silva-Barrera
źródło
To jest nieprawidłowe dla Oracle
a_horse_with_no_name
Właśnie przetestowano w SqlServer, ale możliwe, że masz szansę goz średnikiem, jak w postgres i samym SqlServer. Ale pozostałe podstawowe kody są standardowe sql. Test z średnikami, właśnie to zmieniłem
David Silva-Barrera
[Lub ]są nieważne w standardzie SQL (i Oracle). Oracle nie obsługuje również on updateklauzuli dotyczącej klucza obcego.
a_horse_with_no_name
Masz rację, [ ]są specyficzne dla SqlServer. Wyczyszczę to bardziej. O którym on updatenie mogę nic powiedzieć.
David Silva-Barrera
12

Odpowiedź dla UŻYTKOWNIKÓW 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
źródło
1
Witamy w StackOverflow. Dowiedz się więcej o formatowaniu kodu na stackoverflow.com/editing-help . Zredagowałem kod, aby był bardziej czytelny.
Adrian W
11

Ten PL * SQL zapisze do DBMS_OUTPUT skrypt, który porzuci każde ograniczenie, które nie ma kaskady usuwania i odtworzy je z kaskadą usuwania.

UWAGA: uruchomienie danych wyjściowych tego skryptu odbywa się NA WŁASNE RYZYKO. Najlepiej przeczytać wynikowy skrypt i edytować go przed wykonaniem.

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
źródło
3

Dla każdego, kto używa MySQL:

Jeśli wejdziesz na swoją PHPMYADMINstronę internetową i przejdziesz do tabeli zawierającej klucz obcy, który chcesz zaktualizować, wystarczy kliknąć Relational view znajdujący się na Structurekarcie i zmienić On deleteopcję menu wyboru na Cascade.

Obraz pokazany poniżej:

wprowadź opis obrazu tutaj

James111
źródło
OP pochodzi z 2009 roku, jego pytanie o Oracle zostało oznaczone tagiem, a PHPMYADMIN jest składnikiem oprogramowania innej firmy dla MySQL.
wegetariańska
7
Absolutnie prawdziwe. Ale wyszukałem w Google to pytanie, chcąc wiedzieć, jak to zrobić w MySQL, a Google przywiózł mnie tutaj. Tak, pytanie jest oznaczone tagiem Oracle, więc ta odpowiedź jest nieprawidłowa ... ale będzie przydatna dla czytelników takich jak ja, którzy natkną się na tę odpowiedź. Więc to ma wartość dodaną do tej strony, nawet jeśli nie jest to Oracle szczególnych. Więc dziękuję James111!
Mike Gledhill,
3

Oto przydatne rozwiązanie! Używam SQL Server 2008 R2.

Jeśli chcesz zmodyfikować ograniczenie FK, dodając ON DELETE / UPDATE CASCADE, wykonaj następujące kroki:

NUMER 1:

Kliknij prawym przyciskiem myszy wiązanie i kliknij, aby zmienić

wprowadź opis obrazu tutaj

NUMER 2:

Wybierz swoje ograniczenie po lewej stronie (jeśli jest więcej niż jedno). Następnie po prawej stronie zwiń punkt „ WSTAW I AKTUALIZUJ specyfikację ” i określ akcje w wierszu Usuń regułę lub Aktualizuj regułę zgodnie z potrzebami. Następnie zamknij okno dialogowe.

wprowadź opis obrazu tutaj

NUMER 3:

Ostatnim krokiem jest zapisanie tych modyfikacji (oczywiście!)

wprowadź opis obrazu tutaj

PS: To uratowało mnie od mnóstwa pracy, ponieważ chcę zmodyfikować klucz podstawowy, do którego odwołuje się inna tabela.

Serge Kishiko
źródło
Idealnie, dokładnie to, czego potrzebowałem!
Wildview
1

Jeśli chcesz zmienić klucz obcy bez upuszczania go, możesz zrobić:

ALTER TABLE child_table_name  WITH CHECK ADD FOREIGN KEY(child_column_name)
REFERENCES parent_table_name (parent_column_name) ON DELETE CASCADE
RedPelle
źródło
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
źródło