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

回答:



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

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 2017年

SqlServerでテストされたばかりですがgo、postgresやSqlServer自体のように、セミコロンが付いている可能性があります。ただし、残りのコアコードはSQL標準です。セミコロンでテストし、変更しました
David Silva-Barrera 2017年

[または]標準のSQL(とOracle)は無効です。Oracle on updateは外部キーの句もサポートしていません 。
a_horse_with_no_name 2017年

そうです、[ ]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、あなたがしなければならないすべては、クリックされ、更新する外部キーを持つテーブルにWebページとナビゲートRelational view に位置Structureタブと変更On deleteに選択するメニューオプションをCascade

以下に示す画像:

ここに画像の説明を入力してください


OPは2009年のもので、Oracleの質問がタグ付けされており、PHPMYADMINはMySQLのサードパーティソフトウェアコンポーネントです。
ベガトリピー2015

7
絶対に本当。しかし、MySQLでこれを行う方法を知りたいと思って、私はこの質問をグーグルで検索しました。はい、質問にはOracleのタグが付いているので、この回答は正しくありません...しかし、この回答に出くわした私のような読者には役立ちます。だから、、それがOracle固有のものではない場合でも、このページに値を追加します。James111に感謝します!
Mike Gledhill 2016年

3

これは便利な解決策です!SQL Server 2008 R2を使用しています。

ON DELETE / UPDATE CASCADEを追加してFK制約を変更するには、次の手順に従います。

番号1:

拘束を右クリックし、クリックして修正します

ここに画像の説明を入力してください

2番:

左側で制約を選択します(複数ある場合)。次に、右側で、「INSERT And UPDATE仕様」ポイントを折りたたみ、必要に応じて、ルールの削除またはルールの更新行でアクションを指定します。その後、ダイアログボックスを閉じます。

ここに画像の説明を入力してください

番号3:

最後のステップは、これらの変更を保存することです(もちろん!)

ここに画像の説明を入力してください

PS:別のテーブルで参照されている主キーを変更したいので、多くの作業から私を救いました。


完璧、まさに私が必要としていたもの!
ワイルドビュー

1

ドロップせずに外部キーを変更したい場合は、次のようにします。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.