การวิเคราะห์สถานการณ์ - ซึ่งนำเสนอลักษณะที่เกี่ยวข้องกับเรื่องที่เรียกว่าฐานข้อมูลชั่วคราว - จากมุมมองแนวคิดหนึ่งสามารถกำหนดได้ว่า: (a) " เรื่องราว " ปัจจุบัน " เรื่องราวของบล็อกและ (b)" เรื่องราวในอดีต " บล็อกเรื่องแม้ว่า คล้ายกันเป็นหน่วยงานประเภทต่าง ๆ
นอกจากนั้นเมื่อทำงานในระดับตรรกะของสิ่งที่เป็นนามธรรมข้อเท็จจริง (แสดงโดยแถว) ของชนิดที่แตกต่างจะต้องถูกเก็บไว้ในตารางที่แตกต่างกัน ในกรณีที่อยู่ระหว่างการพิจารณาแม้ในขณะที่คล้ายกันมาก (i) ข้อเท็จจริงเกี่ยวกับ“ปัจจุบัน” รุ่นจะแตกต่างจาก (ii) ข้อเท็จจริงเกี่ยวกับ“ที่ผ่านมา” รุ่น
ดังนั้นฉันขอแนะนำให้จัดการสถานการณ์โดยใช้สองตาราง:
แต่ละคอลัมน์มี (1) คอลัมน์ที่แตกต่างกันเล็กน้อยและ (2) กลุ่มของข้อ จำกัด ที่แตกต่างกัน
กลับไปที่ชั้นความคิดผมคิดว่า -in ธุรกิจ environment- ของผู้เขียนและบรรณาธิการที่มีความคิดที่สามารถเบี่ยงเป็นบทบาทที่สามารถเล่นได้โดยผู้ใช้และสิ่งเหล่านี้ที่สำคัญขึ้นอยู่กับข้อมูลที่มา (ผ่านการดำเนินงานการจัดการลอจิคัลระดับ) และการตีความ (ดำเนินการโดยผู้อ่านและผู้เขียนบล็อกเรื่องราวในระดับภายนอกของระบบข้อมูลคอมพิวเตอร์ด้วยความช่วยเหลือของโปรแกรมแอปพลิเคชันหนึ่งโปรแกรมหรือมากกว่า)
ฉันจะให้รายละเอียดเกี่ยวกับปัจจัยเหล่านี้และประเด็นที่เกี่ยวข้องอื่น ๆ ดังนี้
กฎเกณฑ์ทางธุรกิจ
ตามความเข้าใจของฉันเกี่ยวกับความต้องการของคุณสูตรทางธุรกิจต่อไปนี้ (รวมกันในแง่ของประเภทนิติบุคคลที่เกี่ยวข้องและประเภทของความสัมพันธ์) มีประโยชน์เป็นพิเศษในการสร้างสคีแนวคิดที่สอดคล้องกัน:
- ผู้ใช้เขียนเป็นศูนย์หนึ่งหรือหลายBlogStories
- BlogStoryถือเป็นศูนย์หนึ่งหรือหลายBlogStoryVersions
- ผู้ใช้เขียนเป็นศูนย์หนึ่งหรือหลายBlogStoryVersions
ไดอะแกรม IDEF1X ของที่เก็บข้อมูล
ดังนั้นเพื่อที่จะอธิบายคำแนะนำของฉันโดยอาศัยอำนาจของอุปกรณ์กราฟิกฉันได้สร้างตัวอย่าง IDEF1X แผนภาพที่ได้รับมาจากกฎเกณฑ์ทางธุรกิจสูตรข้างต้นและคุณสมบัติอื่น ๆ ที่ดูเหมือนเกี่ยวข้อง มันแสดงในรูปที่ 1 :

เหตุใดBlogStoryและBlogStoryVersion จึงกำหนดแนวคิดเป็นเอนทิตีที่แตกต่างกันสองประเภท
เพราะ:
BlogStoryVersionอินสแตนซ์ (เช่น“ที่ผ่านมา” อย่างใดอย่างหนึ่ง) เสมอถือเป็นค่าสำหรับUpdatedDateTimeคุณสมบัติในขณะที่BlogStoryเกิดขึ้น (เช่น“ปัจจุบัน” หนึ่ง) ไม่เคยถือมัน
นอกจากนี้เอนทิตีของประเภทเหล่านั้นจะถูกระบุด้วยค่าของคุณสมบัติสองชุดที่แตกต่างกัน: BlogStoryNumber (ในกรณีของการเกิดBlogStory ) และBlogStoryNumberบวกCreatedDateTime (ในกรณีของอินสแตนซ์BlogStoryVersion )
นิยามบูรณาการสำหรับแบบจำลองข้อมูล ( IDEF1X ) เป็นข้อมูลที่ควรเผื่อการสร้างแบบจำลองเทคนิคที่ได้รับการยอมรับว่าเป็นมาตรฐานในเดือนธันวาคมปี 1993 โดยสหรัฐอเมริกาสถาบันมาตรฐานและเทคโนโลยี (NIST) มันขึ้นอยู่กับเนื้อหาทางทฤษฎีในช่วงต้นที่เขียนโดยผู้สร้าง แต่เพียงผู้เดียวของรูปแบบเชิงสัมพันธ์คือดร. EF Codd ; ในมุมมอง Entity-Relationshipของข้อมูลที่พัฒนาโดย Dr. PP Chen ; และยังเกี่ยวกับเทคนิคการออกแบบฐานข้อมูลแบบลอจิคัลสร้างโดย Robert G. Brown
โครงร่าง SQL-DDL เชิงตรรกะ
จากนั้นจากการวิเคราะห์แนวคิดที่นำเสนอก่อนหน้านี้ฉันได้ประกาศการออกแบบระดับตรรกะด้านล่าง:
-- You should determine which are the most fitting
-- data types and sizes for all your table columns
-- depending on your business context characteristics.
-- Also you should make accurate tests to define the most
-- convenient index strategies at the physical level.
-- As one would expect, you are free to make use of
-- your preferred (or required) naming conventions.
CREATE TABLE UserProfile (
UserId INT NOT NULL,
FirstName CHAR(30) NOT NULL,
LastName CHAR(30) NOT NULL,
BirthDate DATETIME NOT NULL,
GenderCode CHAR(3) NOT NULL,
UserName CHAR(20) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT UserProfile_PK PRIMARY KEY (UserId),
CONSTRAINT UserProfile_AK1 UNIQUE ( -- Composite ALTERNATE KEY.
FirstName,
LastName,
BirthDate,
GenderCode
),
CONSTRAINT UserProfile_AK2 UNIQUE (UserName) -- ALTERNATE KEY.
);
CREATE TABLE BlogStory (
BlogStoryNumber INT NOT NULL,
Title CHAR(60) NOT NULL,
Content TEXT NOT NULL,
CoverImageName CHAR(30) NOT NULL,
IsActive BIT(1) NOT NULL,
AuthorId INT NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT BlogStory_PK PRIMARY KEY (BlogStoryNumber),
CONSTRAINT BlogStory_AK UNIQUE (Title), -- ALTERNATE KEY.
CONSTRAINT BlogStoryToUserProfile_FK FOREIGN KEY (AuthorId)
REFERENCES UserProfile (UserId)
);
CREATE TABLE BlogStoryVersion (
BlogStoryNumber INT NOT NULL,
CreatedDateTime DATETIME NOT NULL,
Title CHAR(60) NOT NULL,
Content TEXT NOT NULL,
CoverImageName CHAR(30) NOT NULL,
IsActive BIT(1) NOT NULL,
AuthorId INT NOT NULL,
UpdatedDateTime DATETIME NOT NULL,
--
CONSTRAINT BlogStoryVersion_PK PRIMARY KEY (BlogStoryNumber, CreatedDateTime), -- Composite PK.
CONSTRAINT BlogStoryVersionToBlogStory_FK FOREIGN KEY (BlogStoryNumber)
REFERENCES BlogStory (BlogStoryNumber),
CONSTRAINT BlogStoryVersionToUserProfile_FK FOREIGN KEY (AuthorId)
REFERENCES UserProfile (UserId),
CONSTRAINT DatesSuccession_CK CHECK (UpdatedDateTime > CreatedDateTime) --Let us hope that MySQL will finally enforce CHECK constraints in a near future version.
);
ทดสอบในซอฟท์แวร์ SQL นี้ที่ทำงานบน MySQL 5.6
BlogStoryตาราง
อย่างที่คุณเห็นในการออกแบบการสาธิตฉันได้กำหนดBlogStoryคอลัมน์หลัก (PK สำหรับความกะทัดรัด) ด้วยประเภทข้อมูล INT ในเรื่องนี้คุณอาจต้องการแก้ไขกระบวนการอัตโนมัติในตัวที่สร้างและกำหนดค่าตัวเลขสำหรับคอลัมน์ดังกล่าวในทุกการแทรกแถว หากคุณไม่ต้องการเว้นช่องว่างเป็นครั้งคราวในชุดค่านี้คุณสามารถใช้แอตทริบิวต์AUTO_INCREMENTซึ่งมักใช้ในสภาพแวดล้อม MySQL
เมื่อป้อนBlogStory.CreatedDateTimeจุดข้อมูลส่วนบุคคลทั้งหมดของคุณคุณสามารถใช้ฟังก์ชัน NOW ()ซึ่งจะส่งกลับค่าวันที่และเวลาที่เป็นปัจจุบันในเซิร์ฟเวอร์ฐานข้อมูลที่การดำเนินการ INSERT ที่แน่นอนทันที สำหรับฉันแล้วการฝึกฝนนี้เหมาะสมกว่าและมีแนวโน้มที่จะเกิดข้อผิดพลาดน้อยกว่าการใช้งานประจำภายนอก
โดยมีเงื่อนไขว่าตามที่กล่าวไว้ในความคิดเห็น (ลบออกแล้ว) คุณต้องการหลีกเลี่ยงความเป็นไปได้ในการรักษาBlogStory.Titleค่าที่ซ้ำกันคุณจะต้องตั้งค่าข้อ จำกัดUNIQUEสำหรับคอลัมน์นี้ เนื่องจากความจริงที่ได้รับชื่อเรื่องอาจจะใช้ร่วมกันโดยหลายคน (หรือแม้กระทั่งทั้งหมดของ)“ที่ผ่านมา” BlogStoryVersionsแล้วข้อ จำกัด UNIQUE ควรได้รับการจัดตั้งขึ้นสำหรับBlogStoryVersion.Titleคอลัมน์
ฉันรวมBlogStory.IsActiveคอลัมน์ประเภทBIT (1) (แม้ว่าอาจใช้TINYINT ได้เช่นกัน) ในกรณีที่คุณต้องการฟังก์ชั่นลบ "อ่อน" หรือ "ตรรกะ"
รายละเอียดเกี่ยวกับBlogStoryVersionตาราง
ในทางกลับกันค่า PK ของ BlogStoryVersionตารางประกอบด้วย (a) BlogStoryNumberและ (b) คอลัมน์ที่ชื่อว่าCreatedDateTimeแน่นอนทำเครื่องหมายทันทีที่แม่นยำซึ่งBlogStoryแถวนั้นได้รับการแทรก
BlogStoryVersion.BlogStoryNumberนอกเหนือจากการเป็นส่วนหนึ่งของการ PK ก็ยัง จำกัด เป็นคีย์ต่างประเทศ (FK) ที่อ้างอิงBlogStory.BlogStoryNumber, การกำหนดค่าที่บังคับ Referential Integrityระหว่างแถวของตารางทั้งสองนี้ ในแง่นี้การใช้การสร้างอัตโนมัติของ a BlogStoryVersion.BlogStoryNumberไม่จำเป็นเนื่องจากการตั้งค่าเป็น FK ค่าที่แทรกลงในคอลัมน์นี้จะต้อง "ดึงออกมาจาก" ค่าที่อยู่ในBlogStory.BlogStoryNumberคู่ที่เกี่ยวข้องแล้ว
BlogStoryVersion.UpdatedDateTimeคอลัมน์ควรเก็บรักษาเป็นไปตามคาดจุดในเวลาเมื่อBlogStoryแถวมีการปรับเปลี่ยนและเป็นผลให้เพิ่มเข้าไปในBlogStoryVersionตาราง ดังนั้นคุณสามารถใช้ฟังก์ชัน NOW () ในสถานการณ์นี้ได้เช่นกัน
ช่วงเข้าใจระหว่างBlogStoryVersion.CreatedDateTimeและBlogStoryVersion.UpdatedDateTimeเป็นการแสดงออกทั้งหมดระยะเวลาในระหว่างที่BlogStoryแถวคือ“ปัจจุบัน” หรือ“ปัจจุบัน”
ข้อควรพิจารณาสำหรับ Versionคอลัมน์
มันจะมีประโยชน์ที่จะคิดว่าBlogStoryVersion.CreatedDateTimeเป็นคอลัมน์ที่เก็บค่าที่แสดงให้เห็นโดยเฉพาะอย่างยิ่ง“ที่ผ่านมา” เวอร์ชันของBlogStory ฉันเห็นว่าสิ่งนี้มีประโยชน์มากกว่าVersionIdหรือVersionCodeเพราะผู้ใช้เป็นมิตรในแง่ที่ว่าผู้คนมักจะคุ้นเคยกับแนวคิดเรื่องเวลา ตัวอย่างเช่นผู้เขียนบล็อกหรือผู้อ่านสามารถอ้างถึงBlogStoryVersionในรูปแบบที่คล้ายกับต่อไปนี้:
- “ผมต้องการที่จะเห็นเฉพาะเวอร์ชันของBlogStoryระบุจำนวน
1750ที่ถูกสร้างบน26 August 2015เวลา9:30”
ผู้เขียนและบรรณาธิการบทบาท: ที่มาของข้อมูลและการตีความ
ด้วยวิธีนี้คุณสามารถแยกแยะความแตกต่างที่ถือ“ต้นฉบับ” AuthorIdของคอนกรีตBlogStoryเลือก“ที่เก่าแก่ที่สุด” เวอร์ชันของบางอย่างBlogStoryIdจากBlogStoryVersionตารางโดยอาศัยอำนาจของการใช้MIN () ฟังก์ชั่นBlogStoryVersion.CreatedDateTimeการ
ด้วยวิธีนี้แต่ละBlogStoryVersion.AuthorIdคุ้มค่าที่มีอยู่ในทุกส่วน“ต่อมา” หรือ“ประสบความสำเร็จ” รุ่นแถวบ่งบอกถึงความเป็นธรรมชาติที่ผู้เขียนระบุของแต่ละรุ่นที่อยู่ในมือ แต่ยังสามารถพูดได้ว่าค่าดังกล่าวคือในเวลาเดียวกันแสดงถึงบทบาทเล่นโดยมีส่วนร่วมของผู้ใช้เป็นบรรณาธิการของ“ต้นฉบับ” เวอร์ชันของBlogStory
ใช่AuthorIdค่าที่กำหนดอาจถูกใช้ร่วมกันโดยหลายBlogStoryVersionแถว แต่จริงๆแล้วเป็นข้อมูลชิ้นหนึ่งที่บอกบางอย่างที่มีความสำคัญมากเกี่ยวกับแต่ละเวอร์ชันดังนั้นการทำซ้ำของตัวเลขดังกล่าวจึงเป็นไม่เป็นปัญหา
รูปแบบของคอลัมน์ DATETIME
สำหรับประเภทข้อมูล DATETIME ใช่คุณถูกต้อง“ MySQL ดึงและแสดงค่า DATETIME ในYYYY-MM-DD HH:MM:SSรูปแบบ '' 'แต่คุณสามารถป้อนข้อมูลที่เกี่ยวข้องในลักษณะนี้ได้อย่างมั่นใจและเมื่อคุณต้องทำแบบสอบถามคุณเพียงแค่ต้อง ใช้ประโยชน์จากฟังก์ชัน DATE และ TIMEในตัวเพื่อแสดงค่าที่เกี่ยวข้องในรูปแบบที่เหมาะสมสำหรับผู้ใช้ของคุณ หรือคุณสามารถดำเนินการจัดรูปแบบข้อมูลชนิดนี้ได้อย่างแน่นอนผ่านโค้ดแอปพลิเคชันของคุณ
ความหมายของBlogStoryการปฏิบัติการ UPDATE
ทุกครั้งที่BlogStoryแถวที่ได้รับความทุกข์ทรมานจากการอัพเดทคุณต้องแน่ใจว่าค่าที่สอดคล้องกันนั้นเป็น“ ปัจจุบัน” จนกว่าการดัดแปลงจะเกิดขึ้นจากนั้นแทรกเข้าไปในBlogStoryVersionตาราง ดังนั้นฉันขอแนะนำให้ดำเนินการเหล่านี้ให้สำเร็จภายในการทำธุรกรรมกรดครั้งเดียวเพื่อรับประกันว่าพวกเขาจะได้รับการปฏิบัติในฐานะหน่วยงานที่แบ่งแยกไม่ได้ คุณอาจจ้างทริกเกอร์เช่นกัน แต่พวกเขามักจะทำสิ่งที่ไม่เป็นระเบียบดังนั้นควรพูด
แนะนำVersionIdหรือVersionCodeคอลัมน์
หากคุณเลือก (เนื่องจากสถานการณ์ทางธุรกิจหรือการตั้งค่าส่วนตัว) เพื่อรวมคอลัมน์BlogStory.VersionIdหรือBlogStory.VersionCodeเพื่อแยกความแตกต่างของBlogStoryVersionsคุณควรไตร่ตรองความเป็นไปได้ดังต่อไปนี้:
VersionCodeอาจจะจำเป็นต้องไม่ซ้ำกันใน (i) ทั้งBlogStoryโต๊ะและยังอยู่ใน (ii)BlogStoryVersion(ii)
ดังนั้นคุณต้องใช้วิธีการทดสอบอย่างระมัดระวังและเชื่อถือได้โดยสมบูรณ์เพื่อสร้างและกำหนดCodeค่าแต่ละค่า
บางทีที่VersionCodeค่าอาจจะซ้ำในที่แตกต่างกันBlogStoryเป็นแถว แต่ไม่เคยBlogStoryNumberซ้ำพร้อมกับเดียวกัน เช่นคุณอาจมี:
- a BlogStoryNumber
3- เวอร์ชัน83o7c5cและพร้อมกัน
- a BlogStoryNumber
86- เวอร์ชัน83o7c5cและ
- BlogStoryNumber
958- 83o7c5cรุ่น
ความเป็นไปได้ในภายหลังจะเปิดทางเลือกอื่น:
การรักษาVersionNumberสำหรับBlogStories, ดังนั้นอาจมี:
- BlogStoryNumber
23- รุ่น1, 2, 3… ;
- BlogStoryNumber
650- รุ่น1, 2, 3… ;
- BlogStoryNumber
2254- รุ่น1, 2, 3… ;
- เป็นต้น
โฮลดิ้ง "ดั้งเดิม" และ "รุ่นต่อมา" ในตารางเดียว
แม้ว่าการรักษาทั้งหมดBlogStoryVersionsในเดียวกันแต่ละฐานตารางเป็นไปได้ผมขอแนะนำว่าไม่ต้องทำเพราะคุณจะได้รับการผสมทั้งสองแตกต่างกัน (ความคิด) ประเภทของข้อเท็จจริงซึ่งทำให้มีผลข้างเคียงที่ไม่พึงประสงค์บน
- ข้อ จำกัด ของข้อมูลและการจัดการ (ที่ระดับตรรกะ) พร้อมด้วย
- การประมวลผลและการจัดเก็บที่เกี่ยวข้อง (ที่ระดับกายภาพ)
แต่หากคุณเลือกที่จะปฏิบัติตามแนวทางนั้นคุณยังคงสามารถใช้ประโยชน์จากแนวคิดที่มีรายละเอียดด้านบนเช่น:
- คอมโพสิต PK ประกอบด้วยคอลัมน์ INT (
BlogStoryNumber) และคอลัมน์วันที่และเวลา (CreatedDateTime );
- การใช้ฟังก์ชั่นเซิร์ฟเวอร์เพื่อปรับกระบวนการที่เกี่ยวข้องให้เหมาะสมและ
- ผู้เขียนและบรรณาธิการได้มาบทบาท
เห็นว่าโดยการดำเนินการกับวิธีการดังกล่าวเป็นBlogStoryNumberค่าจะถูกทำซ้ำเร็วที่สุดเท่าที่“ใหม่” รุ่นที่มีการเพิ่มตัวเลือกที่และที่คุณสามารถประเมิน (ซึ่งเป็นมากเหมือนกันที่จะกล่าวถึงในส่วนก่อนหน้า) คือการสร้างBlogStoryPK ประกอบด้วยคอลัมน์BlogStoryNumberและVersionCodeในลักษณะนี้คุณจะสามารถระบุแต่ละเวอร์ชั่นของBlogStoryได้ และคุณสามารถลองด้วยการรวมกันของBlogStoryNumberและVersionNumberเกินไป
สถานการณ์ที่คล้ายกัน
คุณอาจพบคำตอบของฉันสำหรับคำถามของความช่วยเหลือนี้เนื่องจากฉันยังเสนอให้เปิดใช้งานความสามารถทางโลกในฐานข้อมูลที่เกี่ยวข้องเพื่อจัดการกับสถานการณ์ที่คล้ายกัน