เมื่อใดที่จะใช้“ ON CASCADE UPDATE”


420

ฉันใช้ "ON DELETE CASCADE" เป็นประจำ แต่ฉันไม่เคยใช้ "ON CASCADE UPDATE" เนื่องจากฉันไม่แน่ใจในสถานการณ์ที่จะเป็นประโยชน์

เพื่อประโยชน์ของการสนทนาให้ดูรหัสบางส่วน

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
);

สำหรับ "ON DELETE CASCADE" หากผู้ปกครองที่idถูกลบระเบียนในเด็กที่มีparent_id = parent.idจะถูกลบโดยอัตโนมัติ นี่น่าจะไม่มีปัญหา

  1. ซึ่งหมายความว่า "ON CASCADE UPDATE" จะทำสิ่งเดียวกันเมื่อidมีการอัปเดตพาเรนต์หรือไม่

  2. ถ้า (1) เป็นจริงก็หมายความว่าไม่มีความจำเป็นต้องใช้ "ON UPDATE CASCADE" ถ้าparent.idไม่สามารถปรับปรุงได้ (หรือจะไม่ได้รับการปรับปรุง) เช่นเมื่อมันเป็นหรือตั้งค่าเสมอที่จะAUTO_INCREMENT TIMESTAMPนั่นถูกต้องใช่ไหม?

  3. หาก (2) ไม่เป็นความจริงเราควรใช้ "ON CASCADE UPDATE" ในสถานการณ์แบบใด

  4. จะเกิดอะไรขึ้นถ้าฉัน (ด้วยเหตุผลบางอย่าง) อัปเดตchild.parent_idเป็นสิ่งที่ไม่มีอยู่แล้วจะถูกลบโดยอัตโนมัติหรือไม่

ฉันรู้ว่าคำถามบางข้อข้างต้นสามารถทดสอบได้โดยทางโปรแกรมเพื่อให้เข้าใจ แต่ฉันต้องการทราบด้วยเช่นกันว่าเรื่องใด ๆ นี้ขึ้นอยู่กับผู้ขายฐานข้อมูลหรือไม่

กรุณาส่องแสง


1
ดูเพิ่มเติมได้ที่: stackoverflow.com/questions/6894162/ …
XièJìléi

คำตอบ:


468

เป็นความจริงที่ว่าหากคีย์หลักของคุณเป็นเพียงค่าตัวตนที่เพิ่มขึ้นอัตโนมัติคุณจะไม่ได้ใช้งานจริงในวันที่ CASCADE ที่อัพเดท

อย่างไรก็ตามสมมติว่าคีย์หลักของคุณคือบาร์โค้ด UPC 10 หลักและเนื่องจากการขยายคุณต้องเปลี่ยนเป็นบาร์โค้ด UPC 13 หลัก ในกรณีนั้น ON CASCADE UPDATE จะช่วยให้คุณเปลี่ยนค่าคีย์หลักและตารางใด ๆ ที่มีการอ้างอิงคีย์ต่างประเทศกับค่าจะถูกเปลี่ยนตาม

ในการอ้างอิงถึง # 4 หากคุณเปลี่ยน ID ลูกเป็นสิ่งที่ไม่มีอยู่ในตารางหลัก (และคุณมี Referential Integrity) คุณควรได้รับข้อผิดพลาดของรหัสต่างประเทศ


6
เพิ่งต้องใช้ON UPDATE CASCADEตัวเองเพื่ออัปเดตคีย์หลักในตารางเก่าซึ่งไม่ใช้คีย์ที่เพิ่มขึ้นอัตโนมัติ
BlueRaja - Danny Pflughoeft

86
  1. ใช่มันหมายความว่าตัวอย่างเช่นถ้าคุณทำUPDATE parent SET id = 20 WHERE id = 10เด็ก ๆ parent_id ทั้งหมด 10 คนจะได้รับการอัปเดตเป็น 20

  2. หากคุณไม่ได้อัปเดตฟิลด์ที่คีย์ต่างประเทศอ้างถึงการตั้งค่านี้ไม่จำเป็น

  3. นึกถึงการใช้อื่น ๆ ไม่ได้

  4. คุณไม่สามารถทำเช่นนั้นได้เนื่องจากข้อ จำกัด ของคีย์ต่างประเทศจะล้มเหลว


29

ฉันคิดว่าคุณได้คะแนนที่ดีมาก!

หากคุณปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดในการออกแบบฐานข้อมูลและคีย์หลักของคุณจะไม่สามารถอัปเดตได้ (ซึ่งฉันคิดว่าควรเป็นเช่นนั้นเสมอไป) คุณไม่จำเป็นต้องมีON UPDATE CASCADEประโยค

Zedเป็นจุดที่ดีว่าถ้าคุณใช้คีย์ธรรมชาติ (เช่นเขตข้อมูลปกติจากตารางฐานข้อมูลของคุณ) เป็นคีย์หลักของคุณอาจมีบางสถานการณ์ที่คุณต้องอัปเดตคีย์หลักของคุณ อีกตัวอย่างล่าสุดคือ ISBN (หมายเลขหนังสือมาตรฐานสากล) ซึ่งเปลี่ยนจาก 10 เป็น 13 หลัก + ตัวอักษรเมื่อไม่นานมานี้

นี่ไม่ใช่กรณีถ้าคุณเลือกที่จะใช้คีย์ตัวแทน (เช่นระบบที่สร้างขึ้นเทียม) เป็นคีย์หลักของคุณ (ซึ่งจะเป็นตัวเลือกที่ฉันต้องการในทุกโอกาส แต่โอกาสที่หายากที่สุด)

ดังนั้นในที่สุด: หากคีย์หลักของคุณไม่มีการเปลี่ยนแปลงคุณก็ไม่จำเป็นต้องมีON UPDATE CASCADEประโยค

มาร์ค


ปุ่ม "สร้างขึ้นโดยระบบเทียม" คืออะไร UUIDs?
HPWD

1
@HPWD: เพียงคีย์ "ประดิษฐ์" (ค่าที่ไม่ได้ยึดตามหรือมาจากข้อมูลจริงของคุณ) ซึ่งสร้างโดยระบบ - มันอาจเป็น GUID หรือ INT หรือ BIGINT หรืออะไรก็ได้จริง ๆ ไม่ได้ ไม่เป็นไร จุดคือ: ค่าดังกล่าวไม่เกี่ยวข้องกับข้อมูลของคุณเองจริงและระบบกำลังสร้างมูลค่านั้นให้คุณโดยอัตโนมัติ
marc_s

@ marc-s ขอบคุณที่สละเวลาเขียนมันออกมา คำตอบของคุณเหมาะสมอย่างยิ่ง
HPWD

2
ตารางคอลัมน์เดียวที่มีปุ่มธรรมชาติเป็นทางเลือกที่ดี & สะอาดสำหรับความคิดเห็นของฉัน (อย่างน้อยในรสชาติของฐานข้อมูล MySQL) ตัวอย่างเช่นพิจารณาตารางที่colorsมีแถวblue, purpleและyellow, ตารางที่productsมีproduct_colorคอลัมน์, กำลัง FK'ed เข้ากับcolorsตาราง ที่ จำกัด ตัวเลือกเช่น enum แต่ไม่เหมือนกับจำนวนเต็มที่เพิ่มโดยอัตโนมัติไม่จำเป็นต้องมีการเข้าร่วมเพื่อให้ได้ชื่อสี ในกรณีเช่นon update cascadeนี้เป็นความคิดที่ดีถ้าคุณตัดสินใจว่าpurpleควรจะเรียกvioletแทน
okdewit

18

ไม่กี่วันที่ผ่านมาฉันมีปัญหากับทริกเกอร์และฉันพบว่าON UPDATE CASCADEมีประโยชน์ ดูตัวอย่างนี้ (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
);

ในปัญหาของฉันฉันต้องกำหนดการดำเนินการเพิ่มเติม (ทริกเกอร์) เพื่ออัปเดตตารางคอนเสิร์ต การดำเนินการเหล่านั้นต้องแก้ไข club_name และ band_name ฉันไม่สามารถทำได้เนื่องจากการอ้างอิง ฉันไม่สามารถแก้ไขคอนเสิร์ตแล้วจัดการกับตารางสโมสรและวงดนตรี ฉันไม่สามารถทำอย่างอื่นได้ ON UPDATE CASCADEเป็นกุญแจสำคัญในการแก้ปัญหา


3
ความคิดเห็นที่ดี ฉันพบว่าการอัปเดตทั้งหมดยังมีประโยชน์ในกรณีใด ๆ ที่คุณต้องเปลี่ยน ID ของคุณ ฉันยังเห็นด้วยกับคนอื่น ๆ ว่าการเปลี่ยนแปลงนี้ไม่ควรเป็นเรื่องปกติ ตัวอย่างเช่นในกรณีที่คุณอ้างถึงฉันคิดว่าในปริมาณข้อมูลขนาดใหญ่อาจเกี่ยวข้องกับกุญแจต่างประเทศที่ใช้ฟิลด์ข้อความอาจไม่ส่งผลให้ประสิทธิภาพการทำงานเร็วที่สุดของโปรแกรมฐานข้อมูล สังเกตว่าถ้าความสัมพันธ์ระหว่างประเทศในตารางคอนเสิร์ตใช้ club.SERIAL และ bandSERIAL การเปลี่ยนแปลงในชื่อจะไม่ส่งผลกระทบต่อความสัมพันธ์ระหว่างตาราง อย่างไรก็ตามฉันพบว่า ONDATE CASCADE เป็นเครื่องมือที่ยอดเยี่ยมสำหรับการแก้ไขเหตุฉุกเฉิน ขอแสดงความนับถือ
David L

4
นี่คือการออกแบบที่น่าสงสัยซึ่งทำให้เป็นตัวอย่างที่ได้วางแผนไว้ ประเด็นของการรักษาสองSERIALคอลัมน์ในclubและbandเป็นคีย์หลักคืออะไรถ้าคุณอ้างอิงnames แทนคีย์หลักของแต่ละตาราง
sm

กล่าวโดยย่อนี่เป็นประโยชน์ถ้าคุณทำซ้ำฟิลด์จากตารางอื่นและคุณต้องการให้เป็นข้อมูลล่าสุด
Kamil Tomšík

4

ความคิดเห็นของฉันเป็นหลักในการอ้างอิงถึงจุด # 3: ภายใต้สถานการณ์ที่เป็นแบบเรียงซ้อนปรับปรุงใช้ถ้าเราสมมติว่าคีย์หลักไม่สามารถปรับปรุงได้ นี่คือกรณีหนึ่ง

ฉันกำลังจัดการกับสถานการณ์การจำลองแบบซึ่งต้องรวมฐานข้อมูลดาวเทียมจำนวนมากกับต้นแบบ ดาวเทียมแต่ละดวงกำลังสร้างข้อมูลบนตารางเดียวกันดังนั้นการรวมตารางเข้ากับต้นแบบทำให้เกิดการละเมิดข้อ จำกัด ที่เป็นเอกลักษณ์ ฉันกำลังพยายามใช้ ONDATE CASCADE เป็นส่วนหนึ่งของโซลูชันที่ฉันเพิ่มคีย์ใหม่ในระหว่างการรวมแต่ละครั้ง เกี่ยวกับการปรับปรุงแบบเรียงซ้อนควรทำให้กระบวนการนี้ง่ายขึ้นโดยอัตโนมัติส่วนหนึ่งของกระบวนการ


3

มันเป็นคำถามที่ยอดเยี่ยมฉันมีคำถามเดียวกันเมื่อวานนี้ ฉันคิดเกี่ยวกับปัญหานี้โดยเฉพาะการค้นหาถ้ามีบางสิ่งบางอย่างเช่น "ON CASCADE UPDATE" และโชคดีที่นักออกแบบของ SQL ก็คิดเช่นกัน ฉันเห็นด้วยกับ Ted.strauss และฉันยังให้ความเห็นกรณีของ Noran

เมื่อไหร่ที่ฉันจะใช้มัน? เช่นเดียวกับเท็ดชี้ให้เห็นเมื่อคุณทำการรักษาฐานข้อมูลหลาย ๆ ตัวในคราวเดียวและการดัดแปลงหนึ่งในนั้นในตารางเดียวมีการทำซ้ำชนิดใด ๆ ในสิ่งที่เท็ดเรียกว่า "ฐานข้อมูลดาวเทียม" ไม่สามารถเก็บไว้ด้วยต้นฉบับได้ ID และด้วยเหตุผลใดก็ตามที่คุณต้องสร้างขึ้นใหม่ในกรณีที่คุณไม่สามารถอัปเดตข้อมูลในแบบเก่าได้ (เช่นเนื่องจากสิทธิ์หรือในกรณีที่คุณกำลังค้นหาความคงทนในกรณีที่ไม่ยั่งยืน ไม่สมควรได้รับความเคารพอย่างแท้จริงและสมบูรณ์ที่สุดสำหรับกฎทั้งหมดของการทำให้เป็นมาตรฐานเพียงเพราะจะเป็นยูทิลิตี้ที่มีอายุสั้นมาก)

ดังนั้นฉันเห็นด้วยในสองประเด็น:

(A. ) ใช่หลายครั้งการออกแบบที่ดีกว่าสามารถหลีกเลี่ยงได้ แต่

(B. ) ในกรณีของการโยกย้ายการจำลองฐานข้อมูลหรือการแก้ไขเหตุฉุกเฉินมันเป็นเครื่องมือที่ยอดเยี่ยมที่โชคดีที่นั่นเมื่อฉันไปค้นหาว่ามันมีอยู่จริงหรือไม่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.