So fügen Sie 'ON DELETE CASCADE' in die Anweisung ALTER TABLE ein

130

Ich habe eine Fremdschlüsseleinschränkung in meiner Tabelle. Ich möchte ON DELETE CASCADE hinzufügen.

Ich habe das versucht:

Ändern Sie die Tabelle child_table_name
  Ändern Sie die Einschränkung fk_name
  Fremdschlüssel (child_column_name)
  verweist bei der Löschkaskade auf parent_table_name (parent_column_name);

Funktioniert nicht

BEARBEITEN:
Fremdschlüssel existiert bereits, es befinden sich Daten in der Fremdschlüsselspalte.

Die Fehlermeldung, die ich nach dem Ausführen der Anweisung erhalte:

ORA-02275: Eine solche referenzielle Einschränkung ist bereits in der Tabelle vorhanden
Ula Krukar
quelle
Was ist das Problem? Die Anweisung wird abgelehnt, das Löschen erfolgt nicht ..
Thorsten

Antworten:

162

Sie können ON DELETE CASCADEeiner bereits vorhandenen Einschränkung keine hinzufügen . Sie haben dropund re- createdie Einschränkung. Die Dokumentation zeigt, dass die MODIFY CONSTRAINTKlausel nur den Status einer Einschränkung ändern kann (dh: ENABLED/DISABLED...).

Vincent Malgrat
quelle
86

Zuerst dropIhre Fremdschlüssel und versuchen Sie obigen Befehl setzen add constraintstatt modify constraint. Dies ist der Befehl:

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
quelle
24
Er gibt uns den ganzen Code, es ist offensichtlich ein Vorteil für Leute, die nichts mit Postgres zu tun haben
Matthis Kohli
1
@ WiiMaxx Gründer ein Eifersüchtiger. lol Diese Antwort ist wichtiger als die erste Antwort, da dies auch den Code liefert.
Ich bin die dümmste Person
11

Dieses PL * SQL schreibt in DBMS_OUTPUT ein Skript, das jede Einschränkung ohne Löschkaskade löscht und mit Löschkaskade neu erstellt.

HINWEIS: Die Ausführung der Ausgabe dieses Skripts erfolgt auf EIGENES RISIKO. Lesen Sie das resultierende Skript am besten durch und bearbeiten Sie es, bevor Sie es ausführen.

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
quelle
11

Wie zuvor erklärt:

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;

Wie Sie sehen, müssen diese Befehle getrennt werden, zuerst gelöscht und dann hinzugefügt werden.

David Silva-Barrera
quelle
Dies ist ungültig für Oracle
a_horse_with_no_name
Gerade in SqlServer getestet, aber möglicherweise müssen Sie gomit Semikolon wie in Postgres und SqlServer selbst zufällig. Die verbleibenden Kerncodes sind jedoch SQL-Standard. Test mit Semikolons, ich habe es gerade geändert
David Silva-Barrera
Die [oder ]sind in Standard-SQL (und Oracle) ungültig. Oracle unterstützt auch keine on updateKlausel für einen Fremdschlüssel.
a_horse_with_no_name
Sie haben Recht, [ ]sind SqlServer-spezifisch. Ich werde es mehr ausräumen. Über on updatekann ich nichts sagen.
David Silva-Barrera
11

Antwort für MYSQL-BENUTZER:

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
quelle
Willkommen bei StackOverflow. Weitere Informationen zum Formatieren von Code finden Sie unter stackoverflow.com/editing-help . Ich habe den Code für Sie bearbeitet, um ihn besser lesbar zu machen.
Adrian W
3

Für alle, die MySQL verwenden:

Wenn Sie auf Ihre PHPMYADMINWebseite gehen und zu der Tabelle mit dem Fremdschlüssel navigieren, den Sie aktualisieren möchten, müssen Sie nur auf Relational view die StructureRegisterkarte klicken und die On deleteAuswahlmenüoption in ändern Cascade.

Bild unten gezeigt:

Geben Sie hier die Bildbeschreibung ein

James111
quelle
OP stammt aus dem Jahr 2009, die Oracle-Frage ist markiert, und PHPMYADMIN ist eine Softwarekomponente eines Drittanbieters für MySQL.
Vegatripy
7
Absolut wahr. Aber ich habe nach dieser Frage gegoogelt und wollte wissen, wie das in MySQL geht, und Google hat mich hierher gebracht. Ja, die Frage ist mit Oracle gekennzeichnet, daher ist diese Antwort nicht korrekt. Sie ist jedoch für Leser wie mich nützlich, die über diese Antwort stolpern. So ist es nicht erhöhen den Wert dieser Seite, auch wenn es nicht Oracle spezifisch. Also, danke James111!
Mike Gledhill
3

Hier ist eine praktische Lösung! Ich verwende SQL Server 2008 R2.

Gehen Sie folgendermaßen vor, um die FK-Einschränkung durch Hinzufügen von ON DELETE / UPDATE CASCADE zu ändern:

NUMMER 1:

Klicken Sie mit der rechten Maustaste auf die Einschränkung und klicken Sie auf Ändern

Geben Sie hier die Bildbeschreibung ein

NUMMER 2:

Wählen Sie Ihre Einschränkung auf der linken Seite (wenn es mehr als eine gibt). Reduzieren Sie dann auf der rechten Seite den Punkt " INSERT And UPDATE Specification " und fügen Sie die Aktionen in der Zeile "Regel löschen" oder "Regel aktualisieren" entsprechend Ihren Anforderungen ein. Schließen Sie danach das Dialogfeld.

Geben Sie hier die Bildbeschreibung ein

NUMMER 3:

Der letzte Schritt ist das Speichern dieser Änderungen (natürlich!)

Geben Sie hier die Bildbeschreibung ein

PS: Es hat mich vor einer Menge Arbeit bewahrt, da ich einen Primärschlüssel ändern möchte, auf den in einer anderen Tabelle verwiesen wird.

Serge Kishiko
quelle
Perfekt, genau das, was ich auch brauchte!
Wildview
1

Wenn Sie einen Fremdschlüssel ändern möchten, ohne ihn fallen zu lassen, haben Sie folgende Möglichkeiten:

ALTER TABLE child_table_name  WITH CHECK ADD FOREIGN KEY(child_column_name)
REFERENCES parent_table_name (parent_column_name) ON DELETE CASCADE
RedPelle
quelle
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
quelle