เป็นการดีที่จะมีคอลัมน์“ บันทึกสถานะ” ในตารางฐานข้อมูลหรือไม่?


12

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

สามารถทำได้ง่ายเหมือนใช้งาน / ไม่ใช้งานหรือซับซ้อนเช่นอนุมัติ / ลบ / ล็อก / รอดำเนินการ / ปฏิเสธ ฯลฯ สถานะสามารถเก็บไว้ในคอลัมน์จำนวนเต็มบูลีน / สั้นหรือคอลัมน์อักขระเดี่ยวโดยมีการแมปเช่นtrue/ 1= ใช้งานหรือA= อนุมัติแล้ว

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

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

คำถามของฉัน:

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

หมายเหตุ:ฉันอ่านเกี่ยวกับการรักษาตารางประวัติแยกต่างหาก แต่มันดูแย่กว่าในแง่ของการจัดเก็บและต้องสร้างทริกเกอร์และทำให้ทริกเกอร์ทันสมัยอยู่เสมอด้วยสคีมาของตารางที่ถูกติดตาม


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

คำตอบ:


5

ฉันรู้ว่านี่เป็น "Soft Delete"; เพียงทำเครื่องหมายบันทึกเป็น "ลบ" แม้ว่ามันจะไม่ใช่

นี่เป็นแนวปฏิบัติที่ดีหรือเป็นแนวปฏิบัติที่เลวร้ายหรือไม่?

มันขึ้นอยู่กับ.
หากนี่คือสิ่งที่ผู้ใช้ของคุณต้องการ [มาก] ก็อาจเป็นเรื่องดี ในกรณีส่วนใหญ่แม้ว่าฉันจะยืนยันว่ามันเพิ่มค่าใช้จ่ายจำนวนมากเพื่อประโยชน์เล็กน้อย

ส่งผลกระทบต่อการทำให้ข้อมูลกลับสู่ปกติหรือไม่

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

ข้อผิดพลาดที่อาจเกิดขึ้นคืออะไร?

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

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

มีวิธีอื่นในการบรรลุเป้าหมายเดียวกันหรือไม่? (เห็นโน๊ต)

ไม่จริงไม่

คุณจะให้ฐานข้อมูลบังคับใช้ข้อ จำกัด ที่ไม่ซ้ำกันในข้อมูลสำหรับสถานะที่แน่นอนเท่านั้นได้อย่างไร (แต่อนุญาตให้มีการทำซ้ำจำนวนเท่าใดก็ได้สำหรับสถานะอื่น ๆ )

ไม่สะดวก Declarative Referential Integrity (foreign key clauses) เป็นวิธีที่ง่ายที่สุดในการใช้สิ่งนี้และง่ายสำหรับสิ่งต่าง ๆ เช่นเครื่องมือการรายงานเพื่อเลือกกฎเหล่านี้เพื่อกำหนดความสัมพันธ์ระหว่างตาราง กฎดังกล่าวนำไปใช้กับบันทึกทั้งหมดโดยไม่คำนึงถึง "สถานะ" (และไม่มีทางแก้ไข)

อีกทางเลือกหนึ่งคือการใช้ Triggers โค้ดของโพรซีเดอร์ที่บังคับใช้ Referential Integrity ระหว่างตารางและทำทุกสิ่งที่ฉลาดและมีเงื่อนไขตามที่คุณต้องการ นั่นเป็นสิ่งที่ดีสำหรับกรณีเฉพาะของคุณ แต่ข้อดีที่สุดของ Declarative RI ออกไปนอกหน้าต่าง - ไม่มีความสัมพันธ์ที่ตรวจพบได้ระหว่างภายนอกตารางของคุณ นั่นคือ "ซ่อน" ทั้งหมดในทริกเกอร์

เพราะเหตุใดฐานข้อมูลจึงไม่มีคุณลักษณะเหมือน "ถังรีไซเคิล" หรือการติดตามตาราง / การกู้คืนโดยกำเนิดดังนั้นเราจึงสามารถให้ส่วนต่อประสานลบระเบียนจริงโดยไม่ต้องกังวล

ทำไมจะพวกเขา?

นี่คือฐานข้อมูลไม่ใช่ระบบไฟล์หรือสเปรดชีต

สิ่งที่พวกเขาทำพวกเขาทำได้ดีมาก

สิ่งที่พวกเขาไม่ทำอาจมีความต้องการไม่มากนัก


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

9

มันคือการปฏิบัติ ไม่ว่ามันจะดีหรือไม่ดีก็ขึ้นอยู่กับใบสมัครของคุณเป็นอย่างมากและโดยทั่วไปคุณจะต้อง / ต้องการที่จะ "ยกเลิกการลบ" จริงๆ ฉันค่อนข้างสงสัยว่าจะมีแผนวางคอลัมน์แบบนั้นของทุกตารางในระบบ - ดูเหมือนว่าไม่น่าเป็นไปได้มากที่คุณจะต้องนำการยกเลิกการลบไปใช้กับทุกตารางในระบบ และต้องมีการติดตั้งใช้งาน - ในกรณีส่วนใหญ่คุณไม่ได้ยกเลิกการลบแถวเดียวออกจากตารางเดียวคุณต้องเดินผ่านตารางลูกโดยไม่ต้องลบแถวและปรับปรุงตารางที่เกี่ยวข้อง

สำหรับคำถามที่เหลือทั้งหมดมันขึ้นอยู่กับการใช้งานอย่างมาก ตัวอย่างเช่น Oracle มีวิธีการที่แตกต่างกันในการติดตามการเปลี่ยนแปลงทั้งหมดในตาราง - Flashback Data Archive (FDA หรือที่รู้จักกันในชื่อ Total Recall) เป็นวิธีการล่าสุดในการรักษาประวัติเต็มรูปแบบของแถวทุกรุ่นและการเก็บถาวรในฐานข้อมูล รูปแบบการลบนุ่ม ฐานข้อมูลอื่นอาจมีวิธีอื่น ๆ ในการนำรูปแบบไปใช้ ขึ้นอยู่กับฐานข้อมูลและวิธีการใช้งานการลบแบบนุ่มนวลนั้นจะมีผลกระทบต่อประสิทธิภาพการทำงานไม่ว่าจะเป็นข้อ จำกัด และวิธีการบังคับใช้ ฯลฯ หรือไม่หากเรากำลังพูดถึง Oracle คุณสามารถทำได้หลายอย่างด้วยดัชนีตามฟังก์ชัน ใน SQL Server คุณสามารถใช้ดัชนีที่กรองเพื่อจุดประสงค์เดียวกัน


Oracle Flashback เป็นโซลูชั่นที่เหมาะสมที่สุดสำหรับสิ่งที่ฉันต้องการ น่าเสียดายที่มันเป็นกรรมสิทธิ์ของ Oracle
ADTC

4

เป็นเรื่องปกติมากที่จะใช้ฟิลด์ "ตั้งค่าสถานะสำหรับการลบ" ในระบบ MRP / ERP

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

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

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


3

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

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


แนวคิดที่น่าสนใจ ฉันจะตรวจสอบว่าสามารถนำไปใช้งานได้อย่างไร
ADTC

1

ฉันเห็นและใช้รูปแบบนี้บ่อยครั้งสำหรับกรณีการใช้งานเหล่านี้:

  • ข้อมูลเมตาที่คุณต้องการแสดงเฉพาะค่าที่มีผลบังคับใช้ในวันนี้เท่านั้น ตัวอย่างเช่นเลือกจากรายการของผู้ผลิตรถยนต์ในรายการแบบหล่นลงที่เปิดใช้งาน = 1 ค่าตารางสำหรับ ID, VALUE, ENABLED คือ 1, 'ฟอร์ด', 1 และ 2, 'Edsel', 0, 3, 'Toyota' , 1 ให้เฉพาะทางเลือกของฟอร์ดและโตโยต้า
  • สำหรับระบบการจัดการเคสที่กระบวนทัศน์เป็นกรณีที่สามารถอยู่ในสถานะเดียวในแต่ละครั้ง ในกรณีนี้คอลัมน์สลับถูกเรียกว่า CURRENT ด้วยค่า 0 หรือ 1 ที่บังคับใช้โดยข้อ จำกัด การตรวจสอบ ในกรณีที่ย้ายจากสถานะหนึ่งไปอีกสถานะหนึ่งแอปพลิเคชันจะอัพเดตสถานะปัจจุบันของรัฐเก่าเป็น 0 และใหม่เป็น 1

ปัญหาคือการบังคับใช้ความถูกต้องของข้อมูลหากมีมากกว่าหนึ่งแอปพลิเคชันหรือบริการบนเว็บกำลังเขียนลงในตาราง คุณจะมั่นใจได้อย่างไรว่าในกรณีที่มีสถานะปัจจุบันเพียงสถานะเดียว? ในฐานะที่เป็น Justin Cave ชี้ให้เห็นสิ่งนี้สามารถทำได้ใน Oracle โดยการสร้างดัชนีเสมือนจริงตามฟังก์ชั่น


1

เป็นวิธีปฏิบัติที่ดีหากคุณวางแผนที่จะใช้ข้อมูลของคุณสำหรับการรายงาน (แอปพลิเคชันขนาดใหญ่ใด ๆ ที่เพียงพอจะต้องมีรายงาน)

เพื่อเร่งแอปพลิเคชันของคุณคุณไม่ควรปล่อยให้เครื่องมือการรายงานทำงานบนฐานข้อมูลของคุณ เช่นนี้คุณต้องทำสำเนา / ซิงค์กับฐานข้อมูลอื่น

ฉันใช้recordStatusสองสถานะเท่านั้นACTIVEหรือCANCELLEDใช้ร่วมกับการlastUpdatedOnประทับเวลา ฉันใช้recordStatusมากกว่าstatusที่มักจะมีความหมายทางธุรกิจ

เมื่อฉันกำลังซิงค์ฐานข้อมูลการรายงานกับแอปพลิเคชันฉันจะทำฟิลเตอร์lastUpdatedOnเพื่อรู้ว่าฉันจะแทนที่อันใดในด้านการรายงาน

ในด้านการรายงานฉันจะไม่มีrecordStatusหรือlastUpdatedOnฟิลด์เนื่องจากโดยทั่วไปจะไม่ถูกรายงาน เช่นนี้เมื่อฉันเห็นCANCELLEDสถานะฉันจะลบบันทึกออกจากด้านการรายงานด้วยวิธีที่มันมีเพียงบันทึกที่ใช้งานอยู่

สิ่งนี้สามารถขยายไปยังร้านค้าประเภทอื่น ๆ เช่นคลังข้อมูลหรือสำรองข้อมูลที่ต้องการการซิงโครไนซ์เกือบเต็ม อย่างไรก็ตามการรายงานเป็นจุดประสงค์ทั่วไป

หมายเหตุ: ตัวอย่างของคุณApproved, New, Pendingไม่ได้เป็นความคิดที่ดีที่จะนำเป็นข้อมูลร่วมกันเป็นที่มีความหมายทางธุรกิจมันควรจะไปเพียงเพื่อที่มันทำให้ความรู้สึกทางธุรกิจที่ชาญฉลาด

สำหรับล็อคใช้versionNoซึ่งให้ล็อคในแง่ดีสำหรับบันทึกของคุณ

ตัวเลือกอื่นแทนที่จะrecordStatusเป็นrecordActiveและให้มันจัดเก็บแบบbooleanที่ใช้พื้นที่น้อยลงและจัดทำดัชนีน้อยลง แต่ฉันจะกังวลเกี่ยวกับความต้องการในอนาคตที่คุณอาจไม่คาดคิด

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