ทุกตารางควรมีคีย์หลักตัวแทน / ฟิลด์หลักเทียมหรือไม่


33

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

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

เพื่อความชัดเจนคำถามนี้ไม่เกี่ยวกับการประดิษฐ์เทียบกับธรรมชาติ แต่เกี่ยวกับว่ากุญแจเทียมทั้งหมดควรเป็นแบบ Single-field หรือไม่


1
ดูเพิ่มเติมที่dba.stackexchange.com/a/112632/1396
Jack Douglas

คำตอบ:


28

ฉันจะบอกว่าไม่เสมอไป แต่ส่วนใหญ่แล้วใช่ .

นี่คือสถานการณ์บางอย่างที่คุณไม่ต้องการรหัสตัวแทนหรือรหัสเทียม:

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

นอกจากนี้ยังมีบางสถานการณ์ที่คีย์ตัวแทนจำนวนเต็มแบบจำเจที่น่าเบื่อหน่ายที่เพิ่มความน่าเบื่อหน่ายไม่เหมาะ คุณสามารถมีกุญแจที่เป็นตัวแทนตัวอักษรและตัวเลข สิ่งเหล่านี้อาจรวมถึง:

  • สถานการณ์ที่คุณต้องรวมข้อมูลจากหลายแหล่งที่เป็นอิสระ เพื่อหลีกเลี่ยงการชนกันของคีย์คุณอาจใช้ GUID แทนคีย์ IDENTITY
  • สถานการณ์ที่คุณถูกบังคับให้ใช้การแทนค่าคีย์ที่ไม่ใช่ตัวเลข สมมติว่าคุณมีฐานข้อมูลป้ายทะเบียนรถ คีย์ของคุณอาจเป็นค่าตัวอักษรและตัวเลขแทนจำนวนจริง
  • สถานการณ์ที่ความต้องการภายนอกบางอย่างบังคับให้คุณใช้การบีบอัดกับค่าคีย์ของคุณ แทนที่จะใช้ 10 หลักสำหรับ int32 คุณสามารถใช้หกฐาน 36 หลักได้

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

ต้องบอกว่าจำไว้ว่ามีห้องว่างสำหรับ YAGNI ในการใช้แนวคิดนี้ คุณไม่จำเป็นต้องไปบังคับตารางรหัสด้วยรหัสประจำตัวในทุกซอกและซอกแซกของสคีมาของคุณในกรณีที่มีคนตัดสินใจว่าสัญลักษณ์สำหรับเพศชายในตารางพนักงานของคุณต้องเปลี่ยนจาก M เป็น X หรืออะไรที่โง่


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

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

ฉันไม่ได้เปลี่ยนคำถามอย่างที่คุณเห็นจากประวัติศาสตร์เพียงเพิ่มการเน้นที่ฉันคิดว่ามันจะช่วยให้อ่าน skim
แจ็คดักลาส

12

เลขที่

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

ฉันจะพยายามแสดงจุดของฉันในตัวอย่างต่อไปนี้ซึ่ง:

  • brand คือยี่ห้อรถยนต์เช่น Ford, Toyota เป็นต้น
  • dealer เป็นตัวแทนจำหน่ายทางกายภาพเชื่อมโยงกับแบรนด์ (เช่นตัวแทนจำหน่ายฟอร์ดขายฟอร์ดเท่านั้น)
  • model เป็นประเภทของรถยนต์เช่นฟอร์ดโฟกัสฟอร์ดเฟียสต้า ฯลฯ
  • stock คือจำนวนลานหน้ารถปัจจุบันสำหรับตัวแทนจำหน่ายแต่ละราย

ถ้าเราสร้างคีย์ตัวแทนฟิลด์เดียวสำหรับdealerและmodelดังนี้:

create table brand( brand_id integer primary key );

create table dealer( dealer_id integer primary key, 
                     brand_id integer references brand )

create table model( model_id integer primary key, 
                    brand_id integer references brand )

create table stock( model_id integer references model, 
                    dealer_id integer references dealer, 
                    quantity integer,
                      primary key(model_id, dealer_id) )

จากนั้นมันเป็นไปได้ที่จะแทรกแถวเข้าไปในstockฟอร์ดที่เชื่อมโยงdealerกับโมเดล "โตโยต้า" การเพิ่มbrand_id references brandไปstockเพียงทำให้ปัญหาแย่ลง ในทางกลับกันถ้าเราเก็บคีย์ต่างประเทศเป็นส่วนหนึ่งของคีย์หลักดังต่อไปนี้:

create table brand( brand_id integer primary key );

create table dealer( brand_id integer references brand, 
                     dealer_id integer, 
                       primary key(brand_id, dealer_id) )

create table model( brand_id integer references brand, 
                    model_id integer, 
                      primary key(brand_id, model_id) )

create table stock( brand_id integer, 
                    model_id integer, 
                    dealer_id integer, 
                    quantity integer,
                      primary key(brand_id, model_id, dealer_id),
                      foreign key(brand_id, model_id) references model,
                      foreign key(brand_id, dealer_id) references dealer )

ตอนนี้กฏที่ดีลเลอร์ "ฟอร์ด" สามารถสต็อครถยนต์ "ฟอร์ด" นั้นบังคับใช้โดยธรรมชาติโดยรุ่น

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

create table dealer( brand_id integer references brand, 
                     dealer_id serial unique, 
                       primary key(brand_id, dealer_id) )

3
ทำให้ค่าใช้จ่ายสำหรับตัวอย่างตามปกติเกี่ยวกับตัวอย่างที่ไม่จำเป็นต้องสมบูรณ์แบบจากทุกมุมฉันจะบอกว่าการออกแบบประเภทนี้เปราะบางเป็นพิเศษ แม้ว่าจะมีบางอย่างที่น่าพอใจเกี่ยวกับการค้นหาวิธีการใช้ DRI เพื่อบังคับใช้กฎเกณฑ์ทางธุรกิจ แต่ก็ยังใช้ความสามารถบางส่วนของคุณในการตอบสนองต่อการเปลี่ยนแปลง ถ้าโตโยต้าซื้อฟอร์ดหรือตัวแทนจำหน่ายฟอร์ดตัดสินใจขายโตโยต้ามือสองกฎทางธุรกิจที่ขับเคลื่อนด้วย DRI ของคุณจะทำให้คุณปวดหัวในการบำรุงรักษา
Joel Brown

1
ดังนั้น "กฎธุรกิจของคุณอาจเปลี่ยนไป" นั่นเป็นความจริงของกฎเกณฑ์ทางธุรกิจใด ๆ และมักจะเป็นเรื่องยากที่จะสร้างแบบจำลองใหม่ ฉันมักจะได้รับแจ้งว่ากฎเกณฑ์ทางธุรกิจคืออะไร - ฉันไม่ได้ตัดสินใจเอง
แจ็คดักลาส

1
คุณกำลังพูดว่า DRI ไม่ควรใช้เลยเพื่อบังคับใช้กฎเกณฑ์ทางธุรกิจหรือไม่? DRI นั้นเป็นสิ่งเดียวหรือไม่ - แม้แต่กุญแจต่างประเทศที่เรียบง่ายก็คือกฎเกณฑ์ทางธุรกิจที่บังคับใช้โดย DRI
แจ็คดักลาส

4
แน่นอนว่า DRI บังคับใช้กฎเกณฑ์ทางธุรกิจ คุณต้องตัดสินใจว่าจะบังคับใช้กฎใดในโค้ดและในสคีมาของคุณ การเปลี่ยนแปลงสคีมานั้นยากกว่าการเปลี่ยนแปลงโค้ดเกือบทุกครั้ง มีกฎทางธุรกิจสองประเภทที่สามารถเข้าไปในแบบจำลองข้อมูลของคุณได้ หนึ่งอยู่ที่นั่นและหนึ่งไม่ ลักษณะพื้นฐานของข้อมูลที่สำคัญต่อธุรกิจของคุณจะไม่เปลี่ยนแปลงมากนัก วิธีการเฉพาะในที่ที่คุณทำงานกับข้อมูลที่มีมากขึ้นความผันผวน กฎเช่นเดียวกับรถยนต์มีผู้ผลิตอยู่ในรูปแบบข้อมูล กฎอย่างตัวแทนจำหน่ายจะไม่ขายรถยนต์สองยี่ห้อเลย
Joel Brown

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

12

"มันขึ้นอยู่กับ"

ใช่: ฟิลด์ตัวแทนประจำตัว / AUTONUMBER นั้นดีเมื่อคีย์ธรรมชาติกว้างและไม่ใช่ตัวเลข หมายเหตุ: นี่จะถือว่า conflation ของ "PK" และดัชนีคลัสเตอร์ที่เกิดขึ้นโดยค่าเริ่มต้นใน SQL Server และ Sybase เป็นต้น

ไม่: ตารางจำนวนมาก / มากเมื่อคีย์หลัก 2 พอ หรือเมื่อคีย์ธรรมชาติสั้นและยาวคงที่เช่นรหัสสกุลเงิน

แน่นอนผู้ดูแลระบบ ORM (อ่าน: (n) Hibernate) อาจทำตามกฎเหล่านี้ ...

แก้ไข: อ่านคำถามอีกครั้ง

ตารางจำนวนมาก / มากที่มีคีย์พาเรนต์ตัวแทน 2 อันจะมีหลายคอลัมน์ PK
อย่างไรก็ตามไม่จำเป็นต้องมีคอลัมน์ตัวแทนอีกคอลัมน์

หากตารางมีคีย์ตัวแทน (ตัวตน ฯลฯ ) ก็ไม่จำเป็นต้องมีหลายคอลัมน์

คุณสามารถมีซุปเปอร์คีย์ที่มีตัวแทนได้ แต่สิ่งนี้จะบังคับใช้กฎอื่น ๆ (เช่นชนิดย่อย )

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