SQL Server: จะเพิกเฉยต่อความสมบูรณ์ของการอ้างอิงจนถึง COMMIT ได้อย่างไร

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

เนื่องจากการดำเนินการทั้งหมดเกิดขึ้นในธุรกรรม1 ฉันต้องการให้ SQL Server เพิกเฉยต่อความล้มเหลวในความสมบูรณ์ของการอ้างอิงจนกว่าฉันจะเรียก COMMIT TRANSACTION

ตัวอย่างเช่น2:

   Table: Turboencabulators         Table: Marselvanes
   =========================        =======================
PK TurboencabulatorID int    /-> PK MarselvaneID       int
^  MarselvanesID      int --/       HasGrammeter       bit
|                                   PantametricFan     varchar(50)
+-------------------------------    TurboencabulatorID int

หากฉันพยายามแทรก turboencabulator ในตารางใหม่ มันจะล้มเหลวหากไม่มี marselvane อยู่ที่นั่นอยู่แล้ว การกลับคำสั่งมีปัญหาเดียวกัน

เมื่อพยายามลบแถวเก่า ฉันไม่สามารถลบแถวหนึ่งได้จนกว่าอีกแถวจะถูกลบ

ฉันได้ลองทำระบบเฟส n โดยที่แถวทั้งหมดจะถูกแทรกด้วยคอลัมน์ใดๆ ที่อยู่ภายใต้ข้อจำกัดของคีย์นอกที่ตั้งค่าเป็น null จากนั้น ฉันจะอัปเดตแถวที่แทรกทั้งหมด โดยวางค่าที่ขาดหายไปอย่างเหมาะสม จากนั้น หากต้องการลบแถวต้นทาง ฉันจะลบคอลัมน์ทั้งหมดที่ได้รับผลกระทบจาก FK จากนั้นจึงลบแถวจริง3

สิ่งที่ฉันต้องการจริงๆ คือดำเนินการ T-SQL ของฉัน และไม่ให้ SQL Server บอกฉันจนกว่าฉันจะพยายามเรียกคอมมิต

หมายเหตุ

1กระจาย
2ประดิษฐ์ขึ้นสมมุติ
3ซึ่งฉันไม่ได้ทำอีกต่อไป


person Ian Boyd    schedule 26.02.2010    source แหล่งที่มา
comment
เหตุใดคุณจึงมีการอ้างอิงแบบวงกลมระหว่างสองตารางนี้ ดูเหมือนว่านั่นคือปัญหาที่แท้จริง   -  person Samuel Neff    schedule 27.02.2010
comment
@แซม: เห็นด้วย ฉันเดาว่า @Ian ได้ลดความซับซ้อนของปัญหาในการนำเสนอที่นี่ และการอ้างอิงแบบวงกลมที่เกิดขึ้นจริงนั้นต้องใช้หลายขั้นตอนในการตระหนัก คุณพูดอะไรเอียน?   -  person Bob Kaufman    schedule 27.02.2010
comment
@Sam, @Bob: ดูเชิงอรรถ 2 - ในกรณีที่เทอร์โบเอ็นคาบูเลเตอร์ที่มีแผ่นฐานของอะมูไลท์สำเร็จรูปซึ่งถูกปิดล้อมด้วยปลอกลอการิทึมแบบอ่อนได้ในลักษณะที่ตลับลูกปืนกระตุ้นทั้งสองอยู่ในแนวตรงกับพัดลมเพนทาเมตริก คำใบ้เพียงพอ   -  person Ian Boyd    schedule 27.02.2010


คำตอบ (2)


คุณสามารถใช้ได้ ...

ALTER TABLE whatever_table NOCHECK CONSTRAINT ALL 

เพื่อลบการตรวจสอบข้อจำกัดก่อนที่คุณจะเริ่มต้น

และเมื่อเสร็จแล้วให้เปิดเครื่องอีกครั้งด้วย...

ALTER TABLE whatever_table CHECK CONSTRAINT ALL 

นั่นคือสิ่งที่ฉันจะทำต่อไป

-สวมใส่

person Don Dickinson    schedule 26.02.2010
comment
ใช่นั่นคือสิ่งที่ฉันกำลังคิด ฉันแค่ไม่อยาก :( - person Ian Boyd; 27.02.2010

ลองนึกภาพว่าคุณจะนำไปใช้อย่างไร

หากผลลัพธ์ของคีย์นอกจะถูกเลื่อนออกไปจนกว่าจะมีการทำธุรกรรม คอมมิตจะต้องทำการค้นหา/ตรวจสอบ/การดำเนินการเรียงซ้อนทั้งหมดที่ไม่เกิดขึ้นเมื่อแทรก/ลบ/อัปเดต ลองนึกถึงความหมายของข้อจำกัด FK จริงๆ: แผนการดำเนินการส่วนแทรกของคุณจะได้รับ 'คำอธิบายประกอบ' พร้อมการดำเนินการเพิ่มเติมเพื่อตรวจสอบและบังคับใช้ข้อจำกัด FK หากคุณเลื่อนข้อจำกัด ตรรกะเพิ่มเติมในแผนการสอบถามจะต้องไม่ถูกผูกไว้จากช่วงเวลาดำเนินการ และถูกผลักเข้าไปในบริบทของธุรกรรมบางส่วน เพื่อให้ดำเนินการในเวลาที่ยอมรับ การคอมมิตอย่างกะทันหันทั้งหมดเปลี่ยนจากการดำเนินการ 'ธุรกรรมทำเครื่องหมายที่กระทำในบันทึก' แบบสั้นไปเป็นการดำเนินการที่ทำทุกสิ่งที่ถูกข้ามระหว่างการทำธุรกรรมจริง ส่วนที่แย่ที่สุดคือข้อจำกัดอาจล้มเหลว และคิดว่า แอปพลิเคชันจะจัดการกับความล้มเหลวอย่างไร ด้วยข้อจำกัดที่บังคับใช้ในขณะที่ดำเนินการแทรก แอปพลิเคชันสามารถตรวจจับข้อผิดพลาดและดำเนินการแก้ไขได้ โดยจะทราบอย่างชัดเจนถึงสิ่งที่ล้มเหลว แต่ถ้าคุณเลื่อนการดำเนินการนี้ออกไปจนกว่าจะคอมมิต คุณพยายามที่จะคอมมิตและรับข้อยกเว้น ตอนนี้คุณต้องคิดให้ออกว่าอะไรล้มเหลวจากข้อยกเว้นแบบไอ ลองคิดดูสิว่าชีวิตของนักพัฒนาแอพพลิเคชั่นจะซับซ้อนขนาดไหนในกรณีนี้

เหตุผลที่สองว่าทำไมวิธีนี้ใช้ไม่ได้ผลก็คือคุณยังคงแก้ปัญหาไม่ได้ คุณมีตาราง A ที่มีข้อจำกัด FK อยู่ใน B คุณเริ่มทำธุรกรรม แทรกลงใน B จากนั้นแทรกลงใน A จากนั้นลบออกจาก A จากนั้นลบจาก B จากนั้นกระทำ การดำเนินการทั้งหมดเป็นไปตาม FK ในขณะที่เกิดขึ้น ฐานข้อมูลเป็นไปตาม FK ณ เวลาที่กำหนด แต่ถ้าคุณเลื่อนการตรวจสอบข้อจำกัดออกไป พวกเขาจะ ล้มเหลว ณ เวลาคอมมิต!!

ดังนั้นฉันจะบอกว่าความสมบูรณ์ของการอ้างอิงทำงานได้ดีตามที่เป็นอยู่ แต่มันถูกออกแบบมาสำหรับลำดับชั้นของ cascadin ที่ปราศจากวงจร เช่นเดียวกับโครงสร้างข้อมูลและอัลกอริธึม CS จำนวนมาก โครงสร้างจะพังเมื่อมีการแนะนำวงจร ทางออกที่ดีที่สุดคือการวิเคราะห์สคีมาและดูว่าวงจรนั้นหลีกเลี่ยงไม่ได้จริงๆ หรือไม่ กล่าวโดยสรุป การแทรก NULL และการอัปเดตการแทรกโพสต์เป็นทางออกที่ดีที่สุด

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

person Remus Rusanu    schedule 26.02.2010
comment
ฉันเห็นว่าตัวอย่างของฉันไม่ชัดเจน ฉันเข้าใจแล้วว่าใครๆ ก็สามารถเข้าใจผิดได้ ความผิดฉันเอง. - person Ian Boyd; 27.02.2010
comment
ฉันไม่แน่ใจว่าฉันเห็นปัญหา สมมติว่าธุรกรรมมีชุดแฮชอย่างง่ายของ table-key-value ต้องมีอยู่ ดูเหมือนง่ายที่จะรักษาไว้สำหรับแต่ละการแทรกและการลบแทนที่จะบังคับใช้ทันที (การรักษาแฮชเซ็ตดูเหมือนจะไม่ซับซ้อนกว่าการบังคับใช้ในปัจจุบัน) ความล้มเหลวใดๆ จะย้อนกลับธุรกรรมทั้งหมด ดังนั้นจึงไม่มีปัญหาเกี่ยวกับสิ่งที่เกิดขึ้นกับความล้มเหลว ไม่มีปัญหาในการแทรกแล้วลบ เนื่องจากการลบจะเป็นการลบคีย์ออกจากชุดแฮช - person BlueMonkMN; 09.07.2018