รูปแบบการกำหนดข้อมูลสัมพันธ์ในฐานข้อมูล MySQL?


12

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

TABLE list (
  id int auto_increment primary key,
  user_id int, 
  title varchar(255)
);

TABLE list_tasks (
  id int auto_increment primary key,
  list_id int,
  title varchar(255),
  order int,
  is_complete tinyint
);

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

มีวิธีการทั่วไป / รูปแบบการออกแบบสำหรับจัดการกับข้อมูลเวอร์ชันในลักษณะนี้ในฐานข้อมูล MySQL หรือไม่


โปรดทราบว่าพวกเขาเป็นห้องสมุดสำหรับสิ่งนี้ ตัวอย่างเช่นหากคุณใช้ Hibernate จะมี Hibernate Envers ดังนั้นหากคุณมีกรอบการจัดการ DAO ให้ลองค้นหาว่ามีอะไรเช่นนี้หรือไม่
Walfrat

คำตอบ:


9

เป็นเรื่องธรรมดาที่ต้องการทำใน db แม้ว่าคุณจะใส่มันในที่ที่คุณต้องการติดตามการแก้ไขสำหรับรายการ

วิธีหนึ่งในการทำเช่นนี้อาจเป็นการเปลี่ยนแปลงโครงสร้างเช่น

Alter table lists add revision_id integer;
Alter table list_tasks add revision_id integer;

Create Table revisions
{
   id int autoincrement... (revision id)
   list_id int...
   revdate datetime...
}

เมื่อผู้ใช้บันทึกรายการของพวกเขาสร้างการแก้ไขใหม่ในrevisionsตารางด้านบนและกำหนดค่าให้กับรายการในรายการlist_tasksและจากนั้นไปยังรหัสการแก้ไขในlistsเพื่อทำเครื่องหมาย id นั้นเป็นการแก้ไข 'ปัจจุบัน' เมื่อผู้ใช้แก้ไขรายการอย่าแก้ไขรายการที่มีอยู่ - แทนที่จะแทรกรายการใหม่ด้วยรหัสการแก้ไขใหม่และอัปเดตlistตารางด้วยการแก้ไขนั้นเพื่อทำเครื่องหมายว่าเป็นรายการปัจจุบัน

จากนั้นเพื่อแสดงรายการปัจจุบันให้แสดงรายการจากรหัสการแก้ไขปัจจุบันที่ระบุในlistsตาราง ในการเรียกดูเวอร์ชั่นก่อนหน้านี้คุณสามารถรับรายการการเพิกถอนก่อนหน้าของรายการจากตารางการแก้ไขแล้วแสดงรายการแต่ละรายการตามรหัสนั้น


5

โซลูชันนี้ใช้ตารางการตรวจสอบแยกต่างหาก มันมีข้อดีข้อเสีย คุณอาจต้องการลบระเบียนเก่าออกจากตารางหลักของคุณ การปรับปรุงประสิทธิภาพอาจไม่สำคัญ

เพิ่มฟิลด์ต่อไปนี้ในแต่ละตารางที่ตรวจสอบแล้ว:

AddUserID      int <whatever your system uses>
AddDateTime    datetime
UpdateUserID   int <whatever your system uses>
UpdateDateTime datetime
CurrentVersion int
IsDeleted      bit

คุณจะต้องอัปเดตฟิลด์เหล่านี้ทุกครั้งที่มีการเปลี่ยนแปลงข้อมูล CurrentVersion ได้รับการเพิ่มขึ้น 1 (สามารถใช้เป็นวิธีการล็อกเร็กคอร์ด แต่นั่นเป็นคำถามอื่น) IsDeleted จัดเตรียม "soft delete" เพื่อให้สามารถอ้างอิงได้ในอนาคต

ตารางตรวจสอบแยกจากกัน แต่ละตารางควรมีตาราง _Archive หรือ _History ที่สอดคล้องกัน สิ่งเหล่านี้อาจไม่จำเป็นต้องทำดัชนีในลักษณะเดียวกัน เห็นได้ชัดว่าจะไม่ใช้ฟิลด์คีย์หลักเดียว คุณควรจะสามารถสร้างคีย์ผสมจากเขตข้อมูล ID และ UpdateDateTime

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

ฉันได้เห็นงานนี้เป็นอย่างดีในช่วงไม่กี่ปีที่ผ่านมา ฉันต้องการรับฟังข้อเสียเปรียบที่ฉันอาจไม่ได้พิจารณา


ฉัน upvoting นี้เช่นเดียวกับ GrandMasterB ทั้งสองเป็นสิ่งที่ดีและสิ่งที่จะใช้ขึ้นอยู่กับรายละเอียดเพิ่มเติมเกี่ยวกับความต้องการที่เฉพาะเจาะจง
junky

-2

ฉันขอแนะนำให้คุณอ่านบทความโดยละเอียดนี้

https://blog.jondh.me.uk/2011/11/relational-database-versioning-strategies/comment-page-1/#comment-373850

อีกวิธีหนึ่งคือการมีคอลัมน์ version_id ในตารางของคุณและตั้งค่าสถานะ 'ปัจจุบัน' ซึ่งระบุว่าแถวใดเป็นแถวปัจจุบัน ทุกครั้งที่คุณต้องการการอัปเดตคุณสามารถแทรกแถวใหม่และตั้งค่าสถานะ 'current' รุ่นปัจจุบันเป็น 0 / false และเพิ่มแถวใหม่เป็น 1

วิธีนี้คุณสามารถสร้างมุมมองที่แสดงเฉพาะกับชุดธงปัจจุบัน

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