Perbedaan antara On Delete Cascade & On Update Cascade di mysql

45

Aku punya dua tabel di MySQL database- parent, child. Saya mencoba menambahkan referensi kunci asing ke tabel anak saya berdasarkan tabel induk. Apakah ada perbedaan yang signifikan antara ON UPDATE CASCADEdanON DELETE CASCADE

My Parent Table

CREATE TABLE parent (
    id INT NOT NULL,
    PRIMARY KEY (id)
) ENGINE=INNODB;

Pertanyaan saya adalah: Apa perbedaan antara kueri sql berikut.

  1. ON DELETE CASCADE

    CREATE TABLE child (
        id INT, 
        parent_id INT,
        INDEX par_ind (parent_id),
        FOREIGN KEY (parent_id) 
            REFERENCES parent(id)
            ON DELETE CASCADE
    ) ENGINE=INNODB;
    
  2. ON UPDATE CASCADE

    CREATE TABLE child (
        id INT, 
        parent_id INT,
        INDEX par_ind (parent_id),
        FOREIGN KEY (parent_id) 
            REFERENCES parent(id)
            ON UPDATE CASCADE
    ) ENGINE=INNODB;
    
  3. ON UPDATE CASCADE ON DELETE CASCADE

    CREATE TABLE child (
            id INT, 
            parent_id INT,
            INDEX par_ind (parent_id),
            FOREIGN KEY (parent_id) 
                REFERENCES parent(id)
                ON UPDATE CASCADE ON DELETE CASCADE
        ) ENGINE=INNODB;
    

Apakah ada kesalahan dalam kueri? Apa maksud dari pertanyaan ini (1,2 & 3) ?? Apakah mereka sama ???

Lonewolf
sumber
1
ps <nitpick> untuk kelengkapan, yang Anda bicarakan di atas adalah pernyataan DDL (Data Definition Language) , dan bukan query. Kueri pada umumnya dianggap sebagai DML (Data Manipulation Language SELECT, INSERT, UPDATE, DELETE) </nitpick>
Vérace
PS lain lagi untuk kelengkapan, saya bertanya-tanya apa defaultnya. Jadi saya membuat anak tanpa pembaruan atau penghapusan. Apa yang terjadi kemudian adalah bahwa Anda tidak dapat memperbarui atau menghapus orang tua yang memiliki anak tanggungan. Itu masuk akal, namun MySQL tidak selalu merupakan model dari karakteristik khusus itu :-)
Vérace

Jawaban:

64

Sebuah utas yang sangat baik mengenai hal ini dapat ditemukan di sini dan juga di sini . Panduan definitif untuk MySQL, tentu saja, dokumentasi, dapat ditemukan di sini .

Dalam standar SQL 2003 ada 5 tindakan referensial yang berbeda:

  1. RIAM
  2. MEMBATASI
  3. TIDAK ADA TINDAKAN
  4. SET NULL
  5. SET STANDAR

Untuk menjawab pertanyaan:

  1. RIAM

    • ON DELETE CASCADEberarti bahwa jika catatan induk dihapus, catatan anak apa pun juga dihapus. Ini bukan ide yang bagus menurut saya. Anda harus melacak semua data yang pernah ada di database, meskipun ini bisa dilakukan dengan menggunakan TRIGGERs. (Namun, lihat peringatan dalam komentar di bawah).

    • ON UPDATE CASCADEberarti bahwa jika kunci utama induk diubah, nilai anak juga akan berubah untuk mencerminkan itu. Sekali lagi menurut saya, bukan ide yang bagus. Jika Anda mengubah PRIMARY KEYdengan keteraturan (atau bahkan sama sekali!), Ada yang salah dengan desain Anda. Sekali lagi, lihat komentar.

    • ON UPDATE CASCADE ON DELETE CASCADEberarti bahwa jika Anda UPDATE ATAU DELETE orang tua, perubahan akan mengalir ke anak. Ini setara ANDdengan hasil dari dua pernyataan pertama.

  2. MEMBATASI

    • RESTRICTberarti bahwa setiap upaya untuk menghapus dan / atau memperbarui induk akan gagal melempar kesalahan. Ini adalah perilaku default jika suatu tindakan referensial tidak ditentukan secara eksplisit.

      Untuk ON DELETEatau ON UPDATEyang tidak ditentukan, tindakan default selalu RESTRICT`.

  3. TIDAK ADA TINDAKAN

    • NO ACTION: Dari manual . Kata kunci dari SQL standar. Di MySQL, setara dengan RESTRICT. Server MySQL menolak operasi hapus atau perbarui untuk tabel induk jika ada nilai kunci asing terkait di tabel referensi. Beberapa sistem database memiliki cek yang ditangguhkan, dan NO ACTIONmerupakan cek yang ditangguhkan. Di MySQL, batasan kunci asing diperiksa segera, jadi NO ACTIONsama dengan RESTRICT.
  4. SET NULL

    • SET NULL- lagi dari manual. Hapus atau perbarui baris dari tabel induk, dan atur kolom kunci asing atau kolom di tabel anak NULL. Ini bukan yang terbaik dari ide IMHO, terutama karena tidak ada cara "perjalanan waktu" - yaitu melihat kembali ke tabel anak dan mengaitkan catatan dengan NULLs dengan catatan induk yang relevan - baik CASCADEatau menggunakan TRIGGERs untuk mengisi tabel logging untuk melacak perubahan (tetapi, lihat komentar).
  5. SET STANDAR

    • SET DEFAULT. Namun, bagian lain (berpotensi sangat berguna) dari standar SQL yang tidak pernah diimplementasikan oleh MySQL! Mengizinkan pengembang menentukan nilai yang akan ditetapkan kolom kunci asing pada PEMBARUAN atau HAPUS. InnoDB dan NDB akan menolak definisi tabel dengan SET DEFAULTklausa.

Seperti disebutkan di atas, Anda harus meluangkan waktu melihat dokumentasi, di sini .

Vérace
sumber
8
Saya suka jawaban lengkap Anda namun saya tidak setuju dengan pernyataan ini. "Anda harus melacak semua data yang pernah ada dalam database" - ini benar-benar tergantung pada desain dan tujuan database. Misalnya Definisi Resep (saya tidak berbicara makanan - lebih seperti konfigurasi sistem) ketika definisi resep dihapus, tidak masuk akal untuk menjaga anak-anak yang terkait resep itu - yang hanya mengasapi db tanpa alasan. Juga tabel kerja untuk sistem mesin - Saya tidak membutuhkan data lagi; proses dan singkirkan. Selain itu jawaban Anda sangat fantastis.
StixO
2
mirip dengan @StixO Saya paling suka jawaban ini, tapi saya harus tidak setuju dengan mengubah kunci primer. Pasti ada desain di mana ini akan menjadi ide yang buruk tetapi ketika Anda masuk ke database terdistribusi itu bisa sangat diinginkan bahwa kunci utama bebas untuk dipindahkan tanpa kehilangan identitas catatan.
Garet Claborn
"Menurut saya ini bukan ide yang baik. Anda harus melacak semua data yang pernah ada dalam database." - Tidak yakin saya mengerti maksud Anda. Jika Anda menggunakan 'hapus', maka Anda telah memutuskan untuk menghapus sesuatu. Jika Anda memutuskan untuk tidak pernah menghapus apa pun, tidak ada yang akan mengalir. Manfaat memilikinya adalah bahwa dalam aplikasi Anda, Anda dapat yakin bahwa ketika Anda mencari catatan dengan ID asing, Anda tahu bahwa itu akan ada di sana, dan tidak akan ada baris yatim piatu membengkak database Anda jika Anda memutuskan untuk menghapus sesuatu.
Jeff Ryan
Logikanya di sini cukup salah di beberapa tempat, dan bahkan lebih lagi di dunia GDPR baru kami. Saya setuju dengan anggapan bahwa jika kunci primer berubah, itu mungkin merupakan tanda sesuatu yang salah.
Chuck Le Butt
Jika Anda mengubah KUNCI UTAMA dengan keteraturan (atau bahkan sama sekali!), Ada yang salah dengan desain Anda. Maksud Anda ON UPDATE CASCADE mengubah nilai kunci atau nama kunci?
Billal Begueradj
8

Keduanya adalah tindakan yang harus dilakukan, masing-masing, ketika catatan yang direferensikan pada tabel induk mengubah id dan ketika itu dihapus.

Jika Anda menjalankan:

UPDATE parent SET id = -1 WHERE id = 1;

Dan setidaknya ada satu rekaman childdengan parent_id = 1, 1) akan gagal; dalam kasus 2) dan 3), semua catatan dengan parent_id = 1 diperbarui ke parent_id = -1.

Jika Anda menjalankan:

DELETE FROM parent WHERE id = 1;

Dan setidaknya ada satu rekaman childdengan parent_id = 1, 2) akan gagal; dalam kasus 1) dan 3), semua catatan dengan parent_id = 1dihapus.

3) secara sintaksis benar.

Dokumentasi lengkap dapat ditemukan pada manual .

jynus
sumber
6

Saya tidak memiliki reputasi yang cukup untuk mengomentari jawaban sebelumnya. Jadi saya pikir saya akan menguraikan sedikit.

1) ON DELETE CASCADE berarti jika catatan induk dihapus, maka setiap catatan anak referensi juga dihapus. PADA UPDATE secara default ke RESTRICT, yang berarti UPDATE pada catatan induk akan gagal.

2) ON DELETE action default ke RESTRICT, yang berarti DELETE pada record induk akan gagal. TENTANG PEMBARUAN CASCADE akan memperbarui semua catatan anak referensi ketika catatan induk diperbarui.

3) Lihat tindakan CASCADE dalam 1) dan 2) di atas.

Saat menggunakan ID induk dicatat sebagai kunci asing (dalam tabel anak) - pengalaman mengatakan a) jika ID adalah nomor urut yang dihasilkan secara otomatis, maka JANGAN menggunakannya sebagai kunci asing. Gunakan beberapa kunci induk unik lainnya sebagai gantinya. b) jika ID adalah GUID, maka boleh saja menggunakannya sebagai kunci asing. Anda akan melihat kebijaksanaan dalam saran ini ketika Anda mengekspor dan mengimpor catatan atau menyalin catatan ke database lain. Terlalu rumit untuk berurusan dengan nomor urut yang dibuat secara otomatis selama migrasi data ketika mereka dirujuk sebagai kunci asing.

gr
sumber