Kapan menggunakan "ON UPDATE CASCADE"

420

Saya menggunakan "ON DELETE CASCADE" secara teratur tetapi saya tidak pernah menggunakan "ON UPDATE CASCADE" karena saya tidak begitu yakin dalam situasi apa ini akan berguna.

Demi diskusi, mari kita lihat beberapa kode.

CREATE TABLE parent (
    id INT NOT NULL AUTO_INCREMENT,
    PRIMARY KEY (id)
);

CREATE TABLE child (
    id INT NOT NULL AUTO_INCREMENT, parent_id INT,
    INDEX par_ind (parent_id),
    FOREIGN KEY (parent_id)
        REFERENCES parent(id)
        ON DELETE CASCADE
);

Untuk "ON DELETE CASCADE", jika orang tua dengan yang iddihapus, catatan pada anak dengan parent_id = parent.idakan dihapus secara otomatis. Ini seharusnya tidak menjadi masalah.

  1. Ini berarti "ON UPDATE CASCADE" akan melakukan hal yang sama ketika idinduknya diperbarui?

  2. Jika (1) benar, itu berarti bahwa tidak perlu menggunakan "ON UPDATE CASCADE" jika parent.idtidak dapat diupdate (atau tidak akan pernah diperbarui) seperti ketika itu AUTO_INCREMENTatau selalu diatur untuk menjadi TIMESTAMP. Apakah itu benar?

  3. Jika (2) tidak benar, dalam situasi apa kita harus menggunakan "ON UPDATE CASCADE"?

  4. Bagaimana jika saya (karena alasan tertentu) memperbarui child.parent_idmenjadi sesuatu yang tidak ada, kemudian akan dihapus secara otomatis?

Yah, saya tahu, beberapa pertanyaan di atas dapat diuji secara terprogram untuk dipahami tetapi saya ingin juga tahu apakah semua ini tergantung pada vendor database atau tidak.

Tolong beri sedikit cahaya.

NawaMan
sumber
1
Lihat juga: stackoverflow.com/questions/6894162/…
Xiè Jìléi

Jawaban:

468

Memang benar bahwa jika kunci utama Anda hanya nilai identitas yang ditambahkan secara otomatis, Anda tidak akan memiliki kegunaan nyata untuk ON UPDATE CASCADE.

Namun, katakanlah kunci utama Anda adalah kode batang UPC 10 digit dan karena ekspansi, Anda perlu mengubahnya menjadi kode batang UPC 13 digit. Dalam hal ini, ON UPDATE CASCADE akan memungkinkan Anda untuk mengubah nilai kunci utama dan tabel apa pun yang memiliki referensi kunci asing untuk nilai akan diubah sesuai.

Mengacu pada # 4, jika Anda mengubah ID anak ke sesuatu yang tidak ada di tabel induk (dan Anda memiliki integritas referensial), Anda harus mendapatkan kesalahan kunci asing.

C-Pound Guru
sumber
6
Hanya harus menggunakan ON UPDATE CASCADEdiri saya untuk memperbarui kunci utama dalam tabel lama yang tidak menggunakan kunci yang ditambahkan otomatis
BlueRaja - Danny Pflughoeft
86
  1. Ya, itu berarti bahwa misalnya jika Anda melakukan UPDATE parent SET id = 20 WHERE id = 10semua anak, parent_id dari 10 juga akan diperbarui menjadi 20

  2. Jika Anda tidak memperbarui bidang yang dimaksud dengan kunci asing, pengaturan ini tidak diperlukan

  3. Tidak dapat memikirkan penggunaan lainnya.

  4. Anda tidak dapat melakukan itu karena batasan kunci asing akan gagal.

Zed
sumber
29

Saya pikir Anda sudah cukup memaku poin!

Jika Anda mengikuti praktik terbaik desain basis data dan kunci utama Anda tidak pernah dapat diperbarui (yang menurut saya harus selalu menjadi alasannya), maka Anda tidak pernah benar-benar membutuhkan ON UPDATE CASCADEklausa.

Zed membuat poin yang baik, bahwa jika Anda menggunakan kunci alami (misalnya bidang reguler dari tabel database Anda) sebagai kunci utama Anda, maka mungkin ada situasi tertentu di mana Anda perlu memperbarui kunci utama Anda. Contoh terbaru lainnya adalah ISBN (Nomor Buku Standar Internasional) yang berubah dari 10 menjadi 13 digit + karakter beberapa waktu yang lalu.

Ini tidak terjadi jika Anda memilih untuk menggunakan kunci pengganti (misalnya yang dibuat secara sistem) sebagai kunci utama Anda (yang akan menjadi pilihan pilihan saya dalam semua kecuali kesempatan yang paling jarang terjadi).

Jadi pada akhirnya: jika kunci utama Anda tidak pernah berubah, maka Anda tidak perlu ON UPDATE CASCADEklausa.

Marc

marc_s
sumber
Apakah kunci "buatan sistem buatan" itu? UUID?
HPWD
1
@ HPWD: hanya kunci "buatan" (nilai yang tidak berdasarkan atau berasal dari data aktual Anda) yang dihasilkan oleh sistem - itu bisa berupa GUID, atau INT, atau BIGINT - atau apa pun yang sebenarnya - tidak itu penting. Intinya adalah: nilai itu sama sekali tidak terkait dengan data Anda yang sebenarnya - dan sistem menghasilkan nilai itu secara otomatis untuk Anda.
marc_s
@ marc-s terima kasih telah meluangkan waktu untuk menuliskannya. Jawaban Anda masuk akal.
HPWD
2
Tabel satu kolom dengan kunci natural adalah alternatif yang bagus & bersih untuk enum menurut saya (setidaknya dalam rasa MySQL DB). Sebagai contoh, perhatikan tabel colorsdengan baris blue, purple, yellow, dan meja productsdengan product_colorkolom, menjadi FK'ed ke colorsmeja. Itu membatasi pilihan seperti enum, tetapi tidak seperti bilangan bulat yang bertambah secara otomatis, ia tidak memerlukan gabungan untuk mendapatkan nama warna. Dalam kasus seperti itu, on update cascadeadalah ide yang bagus, jika Anda memutuskan yang purpleseharusnya dipanggil violet.
okdewit
18

Beberapa hari yang lalu saya punya masalah dengan pemicu, dan saya sudah tahu itu ON UPDATE CASCADEbisa berguna. Lihatlah contoh ini (PostgreSQL):

CREATE TABLE club
(
    key SERIAL PRIMARY KEY,
    name TEXT UNIQUE
);

CREATE TABLE band
(
    key SERIAL PRIMARY KEY,
    name TEXT UNIQUE
);

CREATE TABLE concert
(
    key SERIAL PRIMARY KEY,
    club_name TEXT REFERENCES club(name) ON UPDATE CASCADE,
    band_name TEXT REFERENCES band(name) ON UPDATE CASCADE,
    concert_date DATE
);

Dalam masalah saya, saya harus mendefinisikan beberapa operasi tambahan (pemicu) untuk memperbarui tabel konser. Operasi-operasi itu harus memodifikasi club_name dan band_name. Saya tidak dapat melakukannya, karena referensi. Saya tidak bisa memodifikasi konser dan kemudian berurusan dengan tabel klub dan band. Saya juga tidak bisa melakukannya dengan cara lain. ON UPDATE CASCADEadalah kunci untuk menyelesaikan masalah.

Ariel Grabijas
sumber
3
Komentar yang bagus Saya temukan pada pembaruan kaskade juga berguna, dalam hal apa pun Anda harus mengubah ID Anda. Saya juga setuju dengan yang lain bahwa perubahan ini seharusnya tidak terlalu khas. Sebagai contoh, dalam hal Anda mengutip, saya berpikir bahwa dalam volume besar data, mungkin terkait kunci asing menggunakan bidang teks mungkin tidak menghasilkan kinerja tercepat dari mesin database. Amati, bahwa jika hubungan luar negeri dalam tabel konser menggunakan club.SERIAL dan band.ERIAL, perubahan nama tidak akan mempengaruhi hubungan antara tabel. Namun, saya menemukan ON UPDATE CASCADE adalah alat yang hebat untuk menyelesaikan keadaan darurat. Salam
David L
4
Ini adalah desain yang dipertanyakan yang membuat contoh yang agak dibuat-buat. Apa gunanya menyimpan dua SERIALkolom clubdan bandsebagai kunci utama jika Anda mereferensikan namedaripada kunci primer setiap tabel?
sm
Singkatnya, ini berguna jika Anda menduplikasi bidang dari tabel lain dan Anda memerlukannya agar selalu terbaru.
Kamil Tomšík
4

Komentar saya terutama mengacu pada poin # 3: dalam keadaan apa ON UPDATE CASCADE berlaku jika kita mengasumsikan bahwa kunci induk tidak dapat diperbarui? Ini ada satu kasus.

Saya berurusan dengan skenario replikasi di mana beberapa database satelit perlu digabungkan dengan master. Setiap satelit menghasilkan data pada tabel yang sama, jadi penggabungan tabel ke master menyebabkan pelanggaran batasan keunikan. Saya mencoba menggunakan ON UPDATE CASCADE sebagai bagian dari solusi di mana saya menambahkan kembali tombol-tombol pada setiap penggabungan. TENTANG PEMBARUAN CASCADE harus menyederhanakan proses ini dengan mengotomatiskan bagian dari proses.

ted.strauss
sumber
3

Ini pertanyaan yang sangat bagus, saya punya pertanyaan yang sama kemarin. Saya memikirkan masalah ini, khususnya PENCARIAN jika ada sesuatu seperti "ON UPDATE CASCADE" dan untungnya para desainer SQL juga memikirkan hal itu. Saya setuju dengan Ted.strauss, dan saya juga berkomentar tentang kasus Noran.

Kapan saya menggunakannya? Seperti yang ditunjukkan Ted, ketika Anda menangani beberapa basis data pada satu waktu, dan modifikasi pada salah satu dari mereka, dalam satu tabel, memiliki jenis reproduksi apa pun yang disebut Ted sebagai "basis data satelit", tidak dapat disimpan dengan yang asli ID, dan untuk alasan apa pun Anda harus membuat yang baru, jika Anda tidak dapat memperbarui data yang lama (misalnya karena izin, atau jika Anda mencari tahan luntur dalam kasus yang sangat singkat sehingga tidak layak mendapatkan penghormatan mutlak dan total terhadap aturan normalisasi total, hanya karena akan menjadi utilitas yang sangat singkat)

Jadi, saya setuju dalam dua hal:

(A.) Ya, seringkali desain yang lebih baik dapat menghindarinya; TAPI

(B.) Dalam kasus migrasi, mereplikasi database, atau menyelesaikan keadaan darurat, itu adalah ALAT BESAR yang untungnya ada di sana ketika saya pergi untuk mencari jika ada.

David L.
sumber