แนวคิดในการพูดถึงแม้ว่าในสภาพแวดล้อมทางธุรกิจของคุณการสั่งซื้อและที่อยู่เป็นแนวคิดที่เกี่ยวข้องอย่างใกล้ชิดพวกเขามีผลต่อเอนทิตีที่แยกกันสองประเภทแต่ละประเภทมีชุดคุณสมบัติที่ใช้งานได้ (หรือแอตทริบิวต์) และข้อ จำกัด
ดังนั้นตามที่ระบุไว้ก่อนหน้านี้ในความคิดเห็นฉันเห็นด้วยกับ@Erikและคุณควรจัดระเบียบรูปแบบตรรกะของฐานข้อมูลของคุณประกาศในองค์ประกอบอื่น ๆ :
- หนึ่งในตารางต่อเนื่องเพื่อให้อยู่ชิ้นส่วนของข้อมูล;
- หนึ่งตารางเพื่อเก็บรายละเอียดเฉพาะลูกค้า
- หนึ่งตารางเพื่อแนบจุดข้อมูลคำสั่งซื้อ และ
- หนึ่งตารางจะมีข้อเท็จจริงเกี่ยวกับความสัมพันธ์ระหว่างลูกค้า (s)และที่อยู่ (e) ;
ตามที่ฉันจะเป็นตัวอย่างด้านล่าง
ไดอะแกรม IDEF1X ของที่เก็บข้อมูล
รูปภาพมีค่าหนึ่งพันคำดังนั้นฉันจึงสร้างไดอะแกรม IDEF1X ที่แสดงในรูปที่ 1เพื่อแสดงความเป็นไปได้ที่เปิดโดยคำแนะนำของฉัน:
ลูกค้า , ที่อยู่และสมาคมของพวกเขา
แสดงให้เห็นว่าผมแสดงให้เห็นการเชื่อมโยงกับหลายต่อหลายคน (M: N) อัตราส่วนระหว่าง cardinality ประเภทนิติบุคคลลูกค้าและที่อยู่ ; วิธีการนี้จะให้ความยืดหยุ่นในอนาคตเพราะตามที่คุณทราบลูกค้าสามารถเก็บที่อยู่หลายแห่งในช่วงเวลาหรือแม้กระทั่งพร้อมกันและที่อยู่เดียวกันสามารถใช้ร่วมกันโดยลูกค้าหลายราย
โดยเฉพาะอย่างยิ่งที่อยู่สามารถนำมาใช้ในหลายวิธีโดยหนึ่งต่อหลาย (1: M) ลูกค้า ; เช่นมันสามารถกำหนดเป็นทางกายภาพและ / หรือมันสามารถตั้งค่าสำหรับการจัดส่งสินค้าและ / หรือการเรียกเก็บเงิน บางทีอินสแตนซ์ที่อยู่เดียวกันสามารถให้บริการตามวัตถุประสงค์ข้างต้นแต่ละอย่างในเวลาเดียวกันหรืออาจครอบคลุมการใช้สองครั้งในขณะที่ที่อยู่ที่แตกต่างกันครอบคลุมที่อยู่ที่เหลือ
aในสภาพแวดล้อมทางธุรกิจบางอย่างลูกค้าสามารถเป็นได้ทั้งบุคคลหรือองค์กร (สถานการณ์ที่อาจบ่งบอกถึงการจัดเรียงที่แตกต่างกันเล็กน้อยดังรายละเอียดในคำตอบนี้เกี่ยวกับโครงสร้าง supertype-subtype) แต่ด้วยวัตถุประสงค์ของการให้ตัวอย่างง่าย ไม่รวมถึงความเป็นไปได้ที่นี่ ในกรณีที่คุณต้องครอบคลุมสถานการณ์นั้นในฐานข้อมูลของคุณโพสต์ของลิงค์ก่อนหน้านี้จะแสดงวิธีการแก้ปัญหาความต้องการดังกล่าว
การสั่งซื้อสินค้า , ที่อยู่ , CustomerAddressและที่อยู่บทบาท
โดยทั่วไปการสั่งซื้อต้องมีเพียงสองชนิดที่อยู่หนึ่งสำหรับการจัดส่งสินค้าและหนึ่งสำหรับการเรียกเก็บเงิน ด้วยวิธีนี้เหมือนกันอยู่เช่นสามารถกรอกทั้งบทบาทสำหรับบุคคลสั่งซื้อแต่แต่ละบทบาทเป็นภาพจากสถานที่ให้บริการที่เกี่ยวข้องเช่นShippingAddressIdหรือBillingAddressId
คำสั่งซื้อนั้นเชื่อมต่อกับที่อยู่ผ่านประเภทเอนทิตีที่เชื่อมโยงกับที่อยู่ลูกค้าด้วยความช่วยเหลือของคีย์หลายตำแหน่งคุณสมบัติสองประการ ได้แก่
- (หมายเลขลูกค้า , ShippingAddressIdid ) และ (หมายเลขลูกค้า , BillingAddressId )
ทั้งสองชี้ไปที่CustomerAddressหลายคีย์หลักของทรัพย์สินที่แสดงเป็น
- ( CUSTOMERNUMBER , AddressId )
... ซึ่งจะช่วยให้เพื่อเป็นตัวแทนของกฎทางธุรกิจที่กำหนดว่า (ก) การสั่งซื้อเช่นจะต้องเชื่อมโยงเฉพาะกับ (ข) ที่อยู่ที่เกิดขึ้นก่อนหน้านี้ที่เกี่ยวข้องกับเฉพาะลูกค้าที่ทำที่สั่งซื้อและไม่เคยมี (c) ไม่ใช่สุ่มลูกค้า - ที่เกี่ยวข้องอยู่
ประวัติสำหรับ (1) ที่อยู่และ (2) สมาคมCustomerAddress
หากคุณต้องการที่จะจัดหาเป็นไปได้ของการปรับเปลี่ยนที่อยู่ชิ้นส่วนของข้อมูลแล้วคุณจะต้องติดตามทุกการเปลี่ยนแปลงข้อมูล ในลักษณะนี้ผมปรากฎอยู่ในฐานะที่เป็น“ตรวจสอบ” ประเภทนิติบุคคลที่รักษาตัวของมันเองAddressHistory
เนื่องจากลักษณะของการเชื่อมต่อระหว่างลูกค้าและที่อยู่ยังสามารถได้รับการแก้ไขอย่างน้อยหนึ่งครั้งฉันจึงได้อธิบายถึงความเป็นไปได้ในการจัดการสมาคมเช่น "ตรวจสอบได้" โดยอาศัยประเภทลูกค้านิติบุคคลที่อยู่
ในแง่นี้ปัจจัยต่าง ๆ ที่เกี่ยวข้องในการถาม - ตอบ 1และQ & A ไม่ใช่ 2 , - เกี่ยวกับการเปิดใช้งานความสามารถทางโลกในฐานข้อมูล - มีความเกี่ยวข้องจริงๆ
รูปแบบโลจิคัล 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 based on the exact
-- data manipulation tendencies of your business domain.
-- As one would expect, you are free to utilize
-- your preferred (or required) naming conventions.
CREATE TABLE Customer (
CustomerNumber INT NOT NULL,
SpecificAttribute CHAR(30) NOT NULL,
ParticularAttribute CHAR(30) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT Customer_PK PRIMARY KEY (CustomerNumber)
);
CREATE TABLE Address (
AddressId INT NOT NULL,
SpecificAttribute CHAR(30) NOT NULL,
ParticularAttribute CHAR(30) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT Address_PK PRIMARY KEY (AddressId)
);
CREATE TABLE CustomerAddress (
CustomerNumber INT NOT NULL,
AddressId INT NOT NULL,
IsPhysical BIT NOT NULL,
IsShipping BIT NOT NULL,
IsBilling BIT NOT NULL,
IsActive BIT NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT CustomerAddress_PK PRIMARY KEY (CustomerNumber, AddressId),
CONSTRAINT CustomerAddressToCustomer_FK FOREIGN KEY (CustomerNumber)
REFERENCES Customer (CustomerNumber),
CONSTRAINT CustomerAddressToAddress_FK FOREIGN KEY (AddressId)
REFERENCES Address (AddressId)
);
CREATE TABLE MyOrder (
CustomerNumber INT NOT NULL,
OrderNumber INT NOT NULL,
ShippingAddressId INT NOT NULL,
BillingAddressId INT NOT NULL,
SpecificAttribute CHAR(30) NOT NULL,
ParticularAttribute CHAR(30) NOT NULL,
OrderDate DATE NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT Order_PK PRIMARY KEY (CustomerNumber, OrderNumber),
CONSTRAINT OrderToCustomer_FK FOREIGN KEY (CustomerNumber)
REFERENCES Customer (CustomerNumber),
CONSTRAINT OrderToShippingAddress_FK FOREIGN KEY (CustomerNumber, ShippingAddressId)
REFERENCES CustomerAddress (CustomerNumber, AddressId),
CONSTRAINT OrderToBillingAddress_FK FOREIGN KEY (CustomerNumber, BillingAddressId)
REFERENCES CustomerAddress (CustomerNumber, AddressId)
);
CREATE TABLE AddressHistory (
AddressId INT NOT NULL,
AuditedDateTime DATETIME NOT NULL,
SpecificAttribute CHAR(30) NOT NULL,
ParticularAttribute CHAR(30) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT AddressHistory_PK PRIMARY KEY (AddressId, AuditedDateTime),
CONSTRAINT AddressHistoryToAddress_FK FOREIGN KEY (AddressId)
REFERENCES Address (AddressId)
);
CREATE TABLE CustomerAddressHistory (
CustomerNumber INT NOT NULL,
AddressId INT NOT NULL,
AuditedDateTime DATETIME NOT NULL,
IsPhysical BIT NOT NULL,
IsShipping BIT NOT NULL,
IsBilling BIT NOT NULL,
IsActive BIT NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT CustomerAddressHistory_PK PRIMARY KEY (CustomerNumber, AddressId, AuditedDateTime),
CONSTRAINT CustomerAddressHistoryToCustomerAddress_FK FOREIGN KEY (CustomerNumber, AddressId)
REFERENCES CustomerAddress (CustomerNumber, AddressId)
);
ถ้าคุณต้องการที่จะดูฉันทดสอบในซอ db <> นี้ที่ทำงานบน SQL Server 2017
History
ตาราง
ข้อความที่ตัดตอนมาจากคำถามของคุณต่อไปนี้สำคัญมาก:
สิ่งที่ฉันกำลังมองหาคือวิธีการตั้งค่าที่อยู่ของฉันดังนั้นเมื่อฉันแก้ไขที่อยู่ใบสั่งจะไม่ได้รับผลกระทบจากความจริงที่ว่าลูกค้าอัปเดตที่อยู่หรือย้ายที่อยู่
AddressHistory
และCustomerAddressHistory
ตารางช่วยในการสร้างความมั่นใจว่ามีการสั่งซื้อสินค้าที่ไม่ได้รับผลกระทบจากที่อยู่การเปลี่ยนแปลงเป็นสิ่งที่แถว“ก่อนหน้านี้” ควรจะเก็บไว้ในแต่ละHistory
ตารางและอาจจะสอบถามเมื่อมีความจำเป็น การดำเนินการ UPDATE และ DELETE ในสองตารางนี้เป็นสิ่งต้องห้าม (การพยายามเปลี่ยนประวัติอาจมีผลทางกฎหมายด้านลบได้)
ช่วงห้อมล้อมระหว่างค่าล้อมรอบในAddressHistory.CreatedDateTime
และAddressHistory.AuditedDateTime
ยืนสำหรับทั้งระยะเวลาในระหว่างที่บางอย่าง“ที่ผ่านมา” Address
แถวก็ถือว่า“ปัจจุบัน”,“ปัจจุบัน” หรือ“มีประสิทธิภาพ” ข้อพิจารณาที่คล้ายกันนี้ใช้กับCustomerAddressHistory
แถว
CustomerAddress.IsActive
บิต (บูล) คอลัมน์จะหมายถึงการชี้ให้เห็นว่าบางAddress
แถวคือ“ใช้งาน” โดยCustomer
แถวหรือไม่ เช่นหากตั้งค่าเป็น 'เท็จ' มันจะสื่อถึงความจริงที่ว่าลูกค้าไม่ได้ใช้ที่อยู่นั้นอีกต่อไปดังนั้นจึงไม่สามารถใช้สำหรับคำสั่งซื้อใหม่ได้
หมายเหตุ : ในทางกลับกันฉันได้เห็นระบบบางอย่างที่ทุกครั้งที่คำสั่งซื้อใหม่มีผลต่อข้อมูลที่อยู่จะต้องป้อนข้อมูล (บางครั้งซ้ำ ๆ ) และที่อยู่ (es) ที่ใช้สำหรับคำสั่งซื้อที่ผ่านมาจะไม่ถูกลบคำสั่งซื้อจะไม่ได้รับผลกระทบจากที่อยู่การเปลี่ยนแปลง)
แนวทางการดำเนินการนี้อาจเกี่ยวข้องกับความซ้ำซ้อนจำนวนมาก แต่เป็นไปได้ว่า - ขึ้นอยู่กับข้อกำหนดด้านข้อมูลที่แน่นอนของโดเมนธุรกิจของคุณ - สามารถใช้งานได้ดังนั้นคุณอาจต้องการประเมินข้อดีข้อเสียเช่นกัน
การดึงข้อมูล
เวอร์ชัน "ปัจจุบัน", "ปัจจุบัน" หรือ "มีผลบังคับใช้" ของการเกิดที่อยู่จะต้องมีอยู่ในแถวในAddress
ตาราง แต่การเลือก "สถานะ" ก่อนหน้าของที่อยู่จากตารางAddressHistory
(หรือจากCustomerAddressHistory
) เป็นเรื่องง่ายและอาจ เป็นแบบฝึกหัดที่น่าสนใจเพื่อพัฒนาทักษะการเขียนโปรแกรม SQL ของคุณ
ด้วยความเคารพต่อหนึ่งในสถานการณ์ที่คุณกล่าวถึงในความคิดเห็นหากคุณต้องการดึง "แถวที่สองถึงเวอร์ชั่นสุดท้าย" ของแต่ละAddress
แถวจากแถวAddressHistory
นั้นคุณจะต้องคำนึงถึงMAX(AddressHistory.AuditedDateTime)
และAddressHistory.AddressId
ที่ตรงกับAddress.AddressId
ค่าเฉพาะที่อยู่ในมือ
ในเรื่องนี้ - อย่างน้อยที่สุดเมื่อสร้างฐานข้อมูลเชิงสัมพันธ์ - มันค่อนข้างสะดวกในการกำหนดสกีมาแนวคิดที่สอดคล้องกันก่อน(ตามกฎเกณฑ์ทางธุรกิจที่เกี่ยวข้อง) และหลังจากนั้นจะประกาศการจัดการ DDL เชิงตรรกะที่ตามมา เมื่อคุณได้รับองค์ประกอบพื้นฐานที่มีเสถียรภาพและเชื่อถือได้ (ซึ่งแน่นอนว่าสามารถวิวัฒนาการได้ตลอดเวลา) ก็ถึงเวลาที่ต้องวิเคราะห์และกำหนดวิธีที่ดีที่สุดในการจัดการ (ผ่าน INSERT, UPDATE, DELETE และ SELECT หรือการรวมกัน) เกี่ยวกับข้อมูล
การรับรู้มุมมองและความช่วยเหลือของโปรแกรมผู้ใช้ปลายทาง
เห็นได้ชัดว่าในระดับภายนอกของสิ่งที่เป็นนามธรรมข้อมูลที่อยู่ถูกรับรู้ (โดยผู้ใช้ปลายทาง) ว่าเป็นส่วนหนึ่งของคำสั่งซื้อและไม่มีอะไรผิดปกติกับสิ่งนั้น แต่นั่นไม่ได้หมายความว่าผู้สร้างแบบจำลองต้องออกแบบชิ้นส่วนที่สำคัญของ ฐานข้อมูลในคำถามเช่นนั้น ในจุดนี้หากมีความต้องการเช่นพิมพ์คำสั่ง "เต็ม" (เป็นไปได้มาก) คุณสามารถ "ทำซ้ำ" ได้ตามต้องการด้วยความช่วยเหลือของผู้ประกอบการที่เข้าร่วมไม่กี่คนและคำสั่ง WHERE ที่เกี่ยวข้อง และอื่น ๆ ) อาจมีการแก้ไขในมุมมองสำหรับการใช้ในอนาคตการส่งผลลัพธ์ที่เกี่ยวข้องไปยังโปรแกรมแอปพลิเคชันที่เกี่ยวข้องซึ่งในทางกลับกันสามารถปรับปรุงการจัดรูปแบบตามความจำเป็น
แน่นอนโปรแกรมประยุกต์ (s) จะเป็นประโยชน์มากเกินไปเมื่อมีการสั่งซื้อจะถูก effectuated; เช่นหน้าต่างเดสก์ท็อป / แอพมือถือหรือเว็บเพจสามารถ:
- แสดงเฉพาะที่อยู่ที่ลูกค้าที่เกี่ยวข้องกำหนดไว้ว่า“ ใช้งานได้” (ผ่าน
CustomerAddress.IsActive
)
- รายการร่วมกันทั้งหมดที่อยู่ที่ลูกค้าได้เปิดใช้งานสำหรับบริการเรียกเก็บเงิน (ผ่าน
CustomerAddress.IsBilling
); และ
- จัดกลุ่มที่อยู่ทั้งหมดที่ลูกค้ากำหนดไว้สำหรับบริการจัดส่ง (ผ่าน
CustomerAddress.IsShipping
)
อำนวยความสะดวกในลักษณะนี้ทุกกระบวนการที่เกี่ยวข้องที่ GUI (เช่นระดับภายนอกของนามธรรมของระบบคอมพิวเตอร์)
แนะนำให้อ่าน
คุณได้ขอ (ในความคิดเห็นที่ถูกลบออกในขณะนี้) ตัวชี้บางอย่างเกี่ยวกับวรรณกรรมฐานข้อมูลเสียง ดังนั้นจึงเป็นสำหรับทฤษฎีวัสดุผมขอแนะนำให้คุณอ่านทุกงานที่เขียนโดยดร. EF Coddเป็นรางวัลทัวริงผู้รับและแน่นอนที่ริเริ่ม แต่เพียงผู้เดียวของรูปแบบความสัมพันธ์ของข้อมูล (ตอนนี้อาจจะมากขึ้นกว่าที่เคยที่เกี่ยวข้อง) รายการนี้รวมถึงบทความและเอกสารที่ทรงอิทธิพลบางส่วนของเขา
สองผลงานที่สำคัญที่ไม่ได้ประกอบในรายการดังกล่าวจะแม่นยำของเขาบรรยาย ACM ทัวริงรางวัลสิทธิฐานข้อมูลเชิงสัมพันธ์: ปฏิบัติมูลนิธิเพื่อผลผลิตจากปี 1981 และหนังสือของเขาที่เป็นสกุลเชิงสัมพันธ์แบบจำลองสำหรับการจัดการฐานข้อมูล: รุ่นที่ 2ซึ่งได้รับการตีพิมพ์ ในปี 1990
บนแนวคิดด้านหน้าออกแบบนิยามแบบบูรณาการสำหรับแบบจำลองข้อมูล (IDEF1X) เป็นเทคนิคที่ฝากฝังอย่างจริงจังที่ถูกกำหนดให้เป็นมาตรฐานในเดือนธันวาคมปี 1993 โดยสหรัฐอเมริกาสถาบันมาตรฐานและเทคโนโลยี (NIST)