Bagaimana cara menambahkan 'ON DELETE CASCADE' di pernyataan ALTER TABLE

130

Saya memiliki batasan kunci asing di meja saya, saya ingin menambahkan ON DELETE CASCADE ke dalamnya.

Saya sudah mencoba ini:

ubah tabel child_table_name
  ubah batasan fk_name
  kunci asing (child_column_name)
  referensi parent_table_name (parent_column_name) di delete cascade;

Tidak bekerja

EDIT:
Kunci asing sudah ada, ada data di kolom kunci asing.

Pesan kesalahan yang saya dapatkan setelah menjalankan pernyataan:

ORA-02275: batasan referensial seperti itu sudah ada dalam tabel
Ula Krukar
sumber
Apa masalahnya? Pernyataan itu ditolak, hapus tidak terjadi ..
Thorsten

Jawaban:

162

Anda tidak dapat menambah ON DELETE CASCADEkendala yang sudah ada. Anda harus dropdan kembali createkendala. The dokumentasi menunjukkan bahwa MODIFY CONSTRAINTklausul hanya dapat memodifikasi keadaan kendala (yaitu: ENABLED/DISABLED...).

Vincent Malgrat
sumber
86

Pertama dropkunci asing Anda dan coba perintah Anda di atas, masukkan add constraintbukan modify constraint. Sekarang ini perintahnya:

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
sumber
24
Dia memberi kita seluruh kode itu dengan sungguh-sungguh keuntungan bagi orang-orang yang tidak ada hubungannya dengan postgres
Matthis Kohli
1
@WiiMaxx Pendiri pria pencemburu. lol Jawaban ini lebih penting daripada jawaban pertama karena ini memberikan kode juga ..
Saya Orang Paling Bodoh
11

PL * SQL ini akan menulis ke skrip DBMS_OUTPUT yang akan menghapus setiap batasan yang tidak memiliki penghapusan kaskade dan membuatnya kembali dengan hapus kaskade.

CATATAN: menjalankan output skrip ini adalah RISIKO ANDA SENDIRI. Terbaik untuk membaca skrip yang dihasilkan dan mengeditnya sebelum menjalankannya.

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

Seperti yang dijelaskan sebelumnya:

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;

Seperti yang Anda lihat, perintah itu harus dipisahkan, pertama-tama menjatuhkan lalu menambahkan.

David Silva-Barrera
sumber
Ini tidak valid untuk Oracle
a_horse_with_no_name
Baru saja diuji di SqlServer, tetapi mungkin Anda harus gomenggunakan semi-colon seperti pada postgres dan SqlServer itu sendiri. Tetapi kode inti tetap adalah standar sql. Tes dengan semi-titik dua, saya baru saja mengubahnya
David Silva-Barrera
The [atau ]yang valid dalam SQL standar (dan Oracle). Oracle juga tidak mendukung on updateklausa untuk kunci asing.
a_horse_with_no_name
Anda benar, [ ]apakah SqlServer spesifik. Saya akan membersihkannya lebih banyak. Tentang on updatesaya tidak bisa mengatakan apa-apa tentang.
David Silva-Barrera
11

Jawaban untuk PENGGUNA 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
sumber
Selamat datang di StackOverflow. Silakan pelajari tentang memformat kode di stackoverflow.com/editing-help . Saya mengedit kode untuk Anda agar lebih mudah dibaca.
Adrian W
3

Bagi siapa pun yang menggunakan MySQL:

Jika Anda menuju ke PHPMYADMINhalaman web Anda dan menavigasi ke tabel yang memiliki kunci asing yang ingin Anda perbarui, yang harus Anda lakukan adalah klik yang Relational view terletak di Structuretab dan ubah On deleteopsi menu pilih ke Cascade.

Gambar yang ditunjukkan di bawah ini:

masukkan deskripsi gambar di sini

James111
sumber
OP mulai 2009, tag pertanyaan Oracle-nya, dan PHPMYADMIN adalah komponen perangkat lunak pihak ketiga untuk MySQL.
vegatripy
7
Sepenuhnya benar. Tapi saya mencari Google untuk pertanyaan ini, ingin tahu bagaimana melakukan ini di MySQL, dan Google membawa saya ke sini. Ya, pertanyaan ini ditandai dengan Oracle, jadi jawaban ini tidak benar ... tetapi akan bermanfaat bagi pembaca seperti saya yang menemukan Jawaban ini. Sehingga tidak menambah nilai ke halaman ini, bahkan jika tidak Oracle tertentu. Jadi, terima kasih James111!
Mike Gledhill
3

Ini adalah solusi praktis! Saya menggunakan SQL Server 2008 R2.

Saat Anda ingin memodifikasi batasan FK dengan menambahkan ON DELETE / UPDATE CASCADE, ikuti langkah-langkah ini:

NOMOR 1:

Klik kanan pada batasan dan klik untuk Memodifikasi

masukkan deskripsi gambar di sini

NOMOR 2:

Pilih kendala Anda di sisi kiri (jika ada lebih dari satu). Kemudian di sisi kanan, taruh titik " INSERT And UPDATE Specification " dan tentukan tindakan pada baris Hapus Aturan atau Perbarui Aturan yang sesuai dengan kebutuhan Anda. Setelah itu, tutup kotak dialog.

masukkan deskripsi gambar di sini

NOMOR 3:

Langkah terakhir adalah menyimpan modifikasi tesis ini (tentu saja!)

masukkan deskripsi gambar di sini

PS: Ini menyelamatkan saya dari banyak pekerjaan karena saya ingin memodifikasi kunci primer yang dirujuk di tabel lain.

Serge Kishiko
sumber
Sempurna, persis apa yang saya butuhkan juga!
Wildview
1

Jika Anda ingin mengubah kunci asing tanpa menjatuhkannya, Anda dapat melakukannya:

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