วิธีที่มีประสิทธิภาพในการติดฉลากคอลัมน์ในฐานข้อมูลคืออะไร?


30

ฉันเคยติดป้ายกำกับคอลัมน์ในฐานข้อมูลของฉันเช่นนี้:

user_id
user_name
user_password_hash

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

วิธีที่มีประสิทธิภาพในการติดฉลากคอลัมน์ในฐานข้อมูลคืออะไร? ทำไม?


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

@ โจฉันจะใช้ MySQL และ SQLite3 เสมอ แต่ควรใช้กับฐานข้อมูลอื่นส่วนใหญ่
โทมัสโอ

@ โจไม่เคยสังเกตว่า Oracle แตกต่างกัน คุณสามารถให้ลิงค์
bernd_k

@bernd_k: ฉันได้เพิ่มลิงก์ไปยังคำตอบของฉันด้านล่าง
Joe

คำตอบ:


33

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

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

ลักษณะของบุคคลคืออะไร: นามสกุลชื่อจริงวันเกิดสัญชาติ ฯลฯ ...

อะไรคือลักษณะของรถยนต์: รุ่นปีสีพลังงาน ฯลฯ ...

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


1
ใช่มันทำให้ฉันโมโหเมื่อมีคนทำเช่นนั้น เมื่อพวกเขาเรียกโต๊ะทั้งหมดของพวกเขา
ออกุส

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

17

นอกจากความคิดเห็นของ Spredzy แล้วให้ติดป้ายคีย์หลักของคุณเหมือนกัน (ID) เพื่อที่ว่าเมื่อคุณเขียนข้อความค้นหาทันทีคุณสามารถเรียกคืนได้อย่างง่ายดาย (u.ID = c.ID) แทนที่จะต้องค้นหา "มันเป็น countryID หรือไม่ , country_ID, countries_ID, countriesID,? "


5
ฉันเคยทำงานกับฐานข้อมูลที่ DBA ตัดสินใจใช้ ID ในบางตารางและ ID ในที่อื่น ๆ และเราได้ตั้งค่า MySQL ให้คำนึงถึงขนาดตัวพิมพ์ ... เวลาสนุก!
Toby

6
เรามักจะใช้ tablename.tablename_id เช่น car.car_id; person.person_id ชื่อเอกพจน์สำหรับตาราง
glasnt

@glasnt การตัดสินใจที่ชาญฉลาด
garik

1
อันที่จริงมันเป็นความคิดที่แย่มากและคุณจะเสียความสามารถในการใช้ส่วนUSINGคำสั่งSQL (เทียบกับข้อมูลจำเพาะ)
Evan Carroll

9

ฉันไม่เห็นด้วยเพิ่มเติมกับภาคผนวกของ David Hall ต่อคำตอบที่ยอดเยี่ยมของ Spredzy เรียบง่ายและเป็นธรรมชาติเป็นวิธีที่จะไป ความสับสนของตารางไม่ควรเป็นปัญหาหากคุณตั้งชื่อตารางตามธรรมชาติเช่นกัน

ไม่รู้สึกว่ามี users.user_id และ cars.car_id เมื่อคุณสามารถมี users.id และ cars.id


7

ฉันจะยืนยันว่าใน schema ฐานข้อมูลทุกคอลัมน์ควรมีชื่อที่ไม่ซ้ำกันในตาราง มีสาเหตุหลายประการ:

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

  • a JOIN b USING (a_id) JOIN c USING (a_id)คุณสามารถใช้ร่วมไวยากรณ์: สะดวกมากและยังช่วยในประเด็นต่อไปนี้

  • หากคุณเรียกใช้คิวรีที่มีการเข้าร่วมจำนวนมากหรือสร้างมุมมองที่เป็นรูปธรรมด้วยSELECT *คุณจะไม่ขัดแย้ง (a และอาจไม่ค่อยมี) คิดเกี่ยวกับการเข้าร่วมperson.name, product.name, country.nameฯลฯ Urgh

  • โดยทั่วไปหากคุณมีข้อสงสัยidประการใหญ่มันเป็นการยากที่จะติดตามความหมายของทุกที่


คุณจะตั้งชื่อคอลัมน์สำหรับชื่อพนักงานและชื่อไซต์ได้อย่างไร คุณจะหลีกเลี่ยงความซ้ำซ้อนของคอลัมน์ป้ายชื่อได้อย่างไร
Spredzy

@Spredzy: ฉันจะไปกับความซ้ำซ้อน
Peter Eisentraut

1
คำตอบสำหรับข้อกังวลเหล่านี้: นามแฝง
Jon of All Trades

7

ลองดูด้วยตัวอย่างของคุณมันจะออกมาเป็นแบบนี้:

USERS
----
id
username,
password
registration_date

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

BTW ฉันคิดว่าคุณควรหาสไตล์ที่คุณชอบและติดกับมัน หากคุณเปลี่ยนบ่อยคุณจะมี schema DB messier


+1 สำหรับ "ค้นหาสไตล์ที่คุณชอบและติดกับมัน" ความสอดคล้องนั้นดีกว่าการปฏิบัติตามมาตรฐานใด ๆ โดยเฉพาะ (แม้ว่าคุณจะยังไม่ได้เลือกมาตรฐาน แต่ก็ดีกว่ามาตรฐานอื่น ๆ )
Jon of All Trades

5

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

ฉันเพิ่งออกจาก บริษัท ที่หนึ่งในนักพัฒนาซอฟต์แวร์ต้องการนำหน้าคีย์หลักและคอลัมน์คีย์ต่างประเทศด้วย pk และ fk สิ่งนี้นำไปสู่สิ่งที่น่ารังเกียจบางประการที่คอลัมน์เริ่มต้นด้วย pkfk (โดยปกติจะเป็นคีย์หลักแบบคอมโพสิตที่ยึดตาม 2 คอลัมน์ซึ่งหนึ่งคอลัมน์เป็นคีย์ต่างประเทศไปยังตารางอื่น)


4
ไม่นับเป็น fk_cluster หรือไม่
Kaji

5

ฉันทำงานในสภาพแวดล้อมที่ชื่อคอลัมน์แต่ละชื่อขึ้นต้นด้วยคำนำหน้าที่ได้มาจากชื่อตารางไม่ใช่การประดิษฐ์ของฉัน แต่ฉันมีความสุขมาก

ชื่อคอลัมน์นึกคิดจะไม่ซ้ำกันในทุกตารางในฐานข้อมูล

ข้อสังเกตบางอย่าง:

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

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


3

ฉันเห็นด้วยกับคำตอบของ Spredzy แต่จะเพิ่มว่าเป็นเรื่องของการตั้งค่าฉันจะใช้ camelCase แทน under_score

ชื่อ, นามสกุลและอื่น ๆ


2
-1 เนื่องจาก CamelCase ไม่ทำงานในระบบฐานข้อมูลทั้งหมดและคุณไม่ได้ระบุระบบฐานข้อมูล ตัวอย่างเช่นมันเป็นข่าวร้ายที่จะใช้ CamelCase ใน Oracle (มันจะต้องใช้อัญประกาศเพื่อสร้างมัน แต่หลังจากนั้นทุกคนเข้าถึงมันจะต้องกระโดดผ่านห่วงเพื่อเข้าถึง / ใช้งาน) ช่างฝันร้ายอะไร
ScottCher

@ScottCher - ฉันไม่รู้ว่ามันไม่ทำงานใน Oracle แต่แล้วฉันไม่ใช่ Oracle DBA ฉันคิดว่าจะต้องดำเนินการตามที่ระบุไว้ว่าชื่อคอลัมน์ต้องปฏิบัติตามกฎที่ DBS กำหนดไว้ก่อน
Toby

3

ในกรณีของ Oracle คุณจะไม่ต้องการตั้งชื่อคอลัมน์ 'id' หรือ 'name' หรือชื่อทั่วไป

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

แต่แม้ว่าคุณจะไม่ได้ใช้ Oracle โดยไม่ต้องเลือกชื่อที่ปรากฏในหลาย ๆ ตารางก็หมายความว่าคุณไม่จำเป็นต้องเจอปัญหาเรื่องนามแฝงทุกครั้งที่คุณเลือกตัวเลือกในสองตาราง:

SELECT
  instrument.name as instrument_name,
  instrument.abbr as instrument_abbr,
  source.name     as source_name,
  source.abbr     as source_abbr,
  ...
FROM ...

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

... และการบันทึกการพิมพ์นำเราไปสู่ปัญหาอื่นใน Oracle - อย่างน้อยใน 8i (เวอร์ชันปัจจุบันเมื่อฉันใช้หลักสูตร Oracle SQL Tuning and Data Modeling) การแคชแผนการดำเนินการขึ้นอยู่กับอักขระตัวแรกเท่านั้น ข้อความค้นหา (จำค่าที่แน่นอนไม่ได้ ... 1024?) ดังนั้นหากคุณมีข้อความค้นหาที่แตกต่างกันไปตามสิ่งที่เกิดขึ้นในตอนท้ายของส่วนคำสั่งที่ไหนและรายการคอลัมน์ที่ยาวมาก ๆ ที่คุณแยกออกมา สามารถทำงานได้อย่างมีประสิทธิภาพเนื่องจากไม่สามารถแคชแผนการดำเนินการได้อย่างถูกต้อง

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

...

เป็นสิ่งที่นอกเหนือไปจากที่:

  • คอลัมน์เป็นเอกพจน์เสมอ (ตารางเป็นพหูพจน์เสมอ)
  • ชื่อทั้งหมดเป็นตัวพิมพ์เล็กในกรณีที่มีบางสิ่งบางอย่าง
  • จากผลข้างต้นให้ใช้เครื่องหมายขีดล่างแทนตัวอูฐ

อัปเดต : สำหรับผู้ที่ไม่คุ้นเคยกับพฤติกรรมการเข้าร่วมของ Oracle ดูตัวอย่างล่าสุดเกี่ยวกับการจัดทำ Oracle SQL: เข้าร่วมเงื่อนไขที่ระบุ:

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

ภายใต้ 'ไวยากรณ์การเข้าร่วมเก่า' (8i และก่อนหน้านี้) 'NATURAL JOIN' เป็นพฤติกรรมการเข้าร่วมเริ่มต้นและฉันเชื่อว่ายังคงเป็นเช่นนั้นหากคุณไม่ได้ระบุเงื่อนไขการเข้าร่วม เมื่อ 'NATURAL JOIN' เป็นตัวเลือกอย่างเป็นทางการใน 9i คำแนะนำทั่วไปไม่ได้ใช้เพราะการตั้งชื่อคอลัมน์ที่ไม่ดีสามารถทำให้คุณตะลึงซึ่งฉันกำลังสนับสนุนชื่อคอลัมน์ที่ดี


4
คุณหมายถึง "Natural Joins" ในย่อหน้าที่สองของคุณ? ถ้าเป็นเช่นนั้นSHUDDER ... เมื่อใดก็ตามที่เป็นไปได้คุณควรระบุว่าคุณต้องการให้ระบบฐานข้อมูลของคุณเข้าร่วมตารางของคุณอย่างไร การปล่อยให้อยู่ในฐานข้อมูลเพื่อตัดสินใจสามารถสร้างผลลัพธ์ที่ไม่คาดคิด / ไม่สอดคล้องกัน นอกจากนี้ Natural Joins ถูก จำกัด ให้เข้าร่วมระหว่างสองตารางและทำให้ค่อนข้าง จำกัด ในการใช้งานของพวกเขา
ScottCher

2
เข้าร่วมธรรมชาติไม่เคยเป็นค่าเริ่มต้น หากไม่มีการเข้าร่วมอย่างชัดเจน / ได้รับการเข้าร่วมคาร์ทีเซียนจะทำ (เช่นแถวทุกแถวในตารางเข้าร่วมกับแถวแต่ละแถวในตารางอื่น) ก่อนที่จะเข้าร่วม ANSI ได้รับการสนับสนุน (เช่นที่ระบุไว้ในส่วนคำสั่ง FROM) จะต้องทำในส่วนคำสั่ง WHERE
Gary

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

2
@ScottCher: "ปล่อยให้มันขึ้นอยู่กับฐานข้อมูลเพื่อตัดสินใจ" - ก่อนอื่นคุณคงหมายถึง "DBMS" มากกว่า "ฐานข้อมูล" ประการที่สองไม่มี AI หรือกลไกมนุษยมนุษย์ใน Oracle; ค่อนข้างNATURAL JOINจะกำหนดขึ้น
onedaywhen

1
@ Joe cross joinคือเคยและจะเป็น 'ค่าเริ่มต้น' เสมอ Oracle ไม่เคยจับคู่กับชื่อคอลัมน์ยกเว้นว่าnatural joinมีการใช้อย่างชัดเจน
Jack Douglas

1
  1. อย่าใช้เครื่องหมายคำพูดคู่"เพราะในการทำเช่นนั้นคุณจะต้องแทนที่ตัวพิมพ์ใหญ่ - เล็กของฐานข้อมูล ข้อมูลจำเพาะ SQL ต้องการตัวบ่งชี้ทั้งหมดจะถูกพับเป็นตัวพิมพ์ใหญ่ ฐานข้อมูลบางตัวเช่น PostgreSQL จะพับเป็นตัวพิมพ์เล็ก หากไม่มีการเสนอราคาใด ๆ มันจะทำงานในฐานข้อมูลทั้งหมดและพวกเขาสามารถพับลงในข้อมูลจำเพาะหรือค่าเริ่มต้นเฉพาะ rdbms
  2. ใช้ under_score ( _) เพราะตามข้างบน - คุณไม่ควรใช้ camelCase
  3. ใช้{entity}_idสำหรับรหัส (และปุ่มต่างประเทศที่ชี้ไปยังรหัสเหล่านั้น) เพราะจากนั้นคุณสามารถใช้USINGข้อ ชื่อคีย์ที่ไม่ซ้ำกันทั่วโลกที่ใช้ในการเข้าร่วมเป็นแบบแผนที่กำหนดไว้ในข้อมูลจำเพาะ

    SELECT *
    FROM employee
    INNER JOIN department
      USING (department_id);
    
      -- compare to
      ON employee.department_id = department.department_id;

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