ฉันสามารถมีคีย์หลักหลายอันในตารางเดียวได้ไหม
ฉันสามารถมีคีย์หลักหลายอันในตารางเดียวได้ไหม
คำตอบ:
ตารางสามารถมีคีย์หลักคอมโพสิตซึ่งเป็นคีย์หลักที่ทำจากคอลัมน์สองคอลัมน์ขึ้นไป ตัวอย่างเช่น:
CREATE TABLE userdata (
userid INT,
userdataid INT,
info char(200),
primary key (userid, userdataid)
);
อัปเดต: นี่คือลิงค์ที่มีคำอธิบายโดยละเอียดเพิ่มเติมของคีย์หลักแบบผสม
คุณสามารถมีคีย์หลักได้เพียงคีย์เดียว แต่คุณสามารถมีได้หลายคอลัมน์ในคีย์หลักของคุณ
คุณสามารถมีดัชนีที่ไม่ซ้ำกันในตารางของคุณซึ่งจะทำงานคล้ายกับคีย์หลักในการที่พวกเขาจะบังคับใช้ค่าที่ไม่ซ้ำกันและจะเพิ่มความเร็วในการสอบถามค่าเหล่านั้น
ตารางสามารถมีปุ่มตัวเลือกหลายตัว คีย์ตัวเลือกแต่ละตัวคือคอลัมน์หรือชุดของคอลัมน์ที่ไม่ซ้ำกันนำมารวมกันและไม่เป็นโมฆะ ดังนั้นการระบุค่าสำหรับคอลัมน์ทั้งหมดของคีย์ตัวเลือกใด ๆ ก็เพียงพอที่จะกำหนดว่ามีหนึ่งแถวที่ตรงกับเกณฑ์หรือไม่มีแถวเลย
คีย์ผู้สมัครเป็นแนวคิดพื้นฐานในตัวแบบข้อมูลเชิงสัมพันธ์
เป็นเรื่องธรรมดาถ้ามีหลายคีย์อยู่ในตารางเดียวเพื่อกำหนดคีย์ตัวเลือกหนึ่งตัวให้เป็นคีย์หลัก นอกจากนี้ยังเป็นเรื่องธรรมดาที่จะทำให้รหัสต่างประเทศใด ๆ ลงในตารางเพื่ออ้างอิงคีย์หลักมากกว่ารหัสอื่น ๆ
ฉันแนะนำแนวทางปฏิบัติเหล่านี้ แต่ไม่มีอะไรในโมเดลเชิงสัมพันธ์ที่ต้องเลือกคีย์หลักในบรรดาปุ่มตัวเลือก
นี่คือคำตอบสำหรับทั้งคำถามหลักและสำหรับคำถามของ @ Kalmi ที่
อะไรคือจุดที่มีคอลัมน์สร้างอัตโนมัติหลายคอลัมน์
รหัสด้านล่างนี้มีคีย์หลักผสม หนึ่งในคอลัมน์นั้นถูกเพิ่มโดยอัตโนมัติ สิ่งนี้จะใช้ได้เฉพาะใน MyISAM เท่านั้น InnoDB จะสร้างข้อผิดพลาด " ข้อผิดพลาด 1075 (42000): คำจำกัดความของตารางที่ไม่ถูกต้องมีคอลัมน์อัตโนมัติได้เพียงคอลัมน์เดียวและต้องกำหนดเป็นคีย์ "
DROP TABLE IF EXISTS `test`.`animals`;
CREATE TABLE `test`.`animals` (
`grp` char(30) NOT NULL,
`id` mediumint(9) NOT NULL AUTO_INCREMENT,
`name` char(30) NOT NULL,
PRIMARY KEY (`grp`,`id`)
) ENGINE=MyISAM;
INSERT INTO animals (grp,name) VALUES
('mammal','dog'),('mammal','cat'),
('bird','penguin'),('fish','lax'),('mammal','whale'),
('bird','ostrich');
SELECT * FROM animals ORDER BY grp,id;
Which returns:
+--------+----+---------+
| grp | id | name |
+--------+----+---------+
| fish | 1 | lax |
| mammal | 1 | dog |
| mammal | 2 | cat |
| mammal | 3 | whale |
| bird | 1 | penguin |
| bird | 2 | ostrich |
+--------+----+---------+
(เคยศึกษาสิ่งเหล่านี้มามาก)
คีย์ผู้สมัคร - ชุดค่าผสมของคอลัมน์ขั้นต่ำที่จำเป็นในการระบุแถวของตาราง
แป้นผสม - 2 คอลัมน์ขึ้นไป
แหล่งที่มา:
https://en.wikipedia.org/wiki/Superkey
https://en.wikipedia.org/wiki/Candidate_key
https://en.wikipedia.org/wiki/Primary_key
https://en.wikipedia.org / วิกิพีเดีย / Compound_key
ดังที่กล่าวไว้โดยคนอื่น ๆ มันเป็นไปได้ที่จะมีคีย์หลักหลายคอลัมน์ ควรสังเกตว่าถ้าคุณมีการพึ่งพาการทำงานบางอย่างที่ไม่ได้แนะนำโดยคีย์คุณควรพิจารณาปรับความสัมพันธ์ของคุณให้เป็นมาตรฐาน
ตัวอย่าง:
Person(id, name, email, street, zip_code, area)
สามารถมีการพึ่งพาการทำงานระหว่างid -> name,email, street, zip_code and area
แต่มักจะzip_code
มีความเกี่ยวข้องกับarea
และทำให้มีการทำงาน dependecy zip_code -> area
ภายในระหว่าง
ดังนั้นหนึ่งอาจพิจารณาแยกเป็นตารางอื่น:
Person(id, name, email, street, zip_code)
Area(zip_code, name)
คีย์หลักเป็นสัญลักษณ์ที่โชคร้ายมากเนื่องจากความหมายแฝงของ "หลัก" และความสัมพันธ์ของจิตใต้สำนึกซึ่งเป็นผลมาจากโมเดลเชิงตรรกะ ฉันจึงหลีกเลี่ยงการใช้มัน แต่ฉันอ้างถึง Surrogate Key ของตัวแบบทางกายภาพและ Natural Key (s) ของ Logical Model
มันเป็นสิ่งสำคัญที่ Logical Model สำหรับทุกเอนทิตี้ต้องมี "แอตทริบิวต์ธุรกิจ" อย่างน้อยหนึ่งชุดซึ่งประกอบด้วยคีย์สำหรับเอนทิตี Boyce, Codd, Date และ al อ้างถึงสิ่งเหล่านี้ในรูปแบบเชิงสัมพันธ์เป็นคีย์ผู้สมัคร เมื่อเราสร้างตารางสำหรับเอนทิตีเหล่านี้คีย์ผู้สมัครของพวกเขาจะกลายเป็นคีย์ธรรมชาติในตารางเหล่านั้น ผ่านทาง Natural Keys เท่านั้นที่ผู้ใช้สามารถระบุแถวในตารางได้ เนื่องจากกุญแจตัวแทนควรถูกซ่อนจากผู้ใช้เสมอ นี่เป็นเพราะคีย์ตัวแทนไม่มีความหมายทางธุรกิจ
อย่างไรก็ตามแบบจำลองทางกายภาพสำหรับตารางของเราในหลาย ๆ กรณีจะไม่มีประสิทธิภาพโดยไม่ต้องใช้คีย์ตัวแทน จำได้ว่าคอลัมน์ที่ไม่ครอบคลุมสำหรับดัชนีที่ไม่ทำคลัสเตอร์สามารถพบได้ (โดยทั่วไป) ผ่านการค้นหาคีย์ลงในดัชนีคลัสเตอร์ (ละเว้นตารางที่นำมาใช้เป็นฮีปสักครู่) เมื่อคีย์ธรรมชาติที่มีอยู่ของเรามีความกว้าง (1) นี้จะเพิ่มความกว้างของโหนดลีฟที่ไม่ใช่คลัสเตอร์ของเราเพิ่มความต้องการหน่วยเก็บข้อมูลและเข้าถึงการอ่านเพื่อค้นหาและสแกนดัชนีที่ไม่ใช่คลัสเตอร์นั้น และ (2) ลดพัดลมออกจากดัชนีกลุ่มของเราเพิ่มความสูงของดัชนีและขนาดดัชนีเพิ่มการอ่านและการจัดเก็บข้อกำหนดสำหรับดัชนีคลัสเตอร์ของเราอีกครั้ง และ (3) เพิ่มข้อกำหนดแคชสำหรับดัชนีคลัสเตอร์ของเรา ไล่ดัชนีและข้อมูลอื่น ๆ ออกจากแคช
นี่คือที่ซึ่งตัวแทน Surrogate Key ขนาดเล็กที่กำหนดให้ RDBMS ในฐานะ "คีย์หลัก" ได้รับประโยชน์ เมื่อตั้งค่าเป็นคีย์การทำคลัสเตอร์เพื่อใช้สำหรับการค้นหาคีย์ในดัชนีคลัสเตอร์จากดัชนีที่ไม่ทำคลัสเตอร์และการค้นหาคีย์ต่างประเทศจากตารางที่เกี่ยวข้องข้อเสียทั้งหมดเหล่านี้จะหายไป ดัชนีกลุ่มพัดลมของเราเพิ่มขึ้นอีกครั้งเพื่อลดความสูงและขนาดดัชนีคลัสเตอร์ลดภาระแคชสำหรับดัชนีกลุ่มของเราลดการอ่านเมื่อเข้าถึงข้อมูลผ่านกลไกใด ๆ (ไม่ว่าจะเป็นการสแกนดัชนีค้นหาดัชนีค้นหาคีย์ที่ไม่ใช่คลัสเตอร์หรือค้นหาคีย์ต่างประเทศ) และลดความต้องการพื้นที่เก็บข้อมูลสำหรับดัชนีทั้งแบบคลัสเตอร์และแบบไม่รวมกลุ่มของตารางของเรา
โปรดทราบว่าผลประโยชน์เหล่านี้จะเกิดขึ้นเมื่อคีย์ตัวแทนเท่านั้นมีทั้งขนาดเล็กและคีย์การทำคลัสเตอร์ หากใช้ GUID เป็นคีย์การจัดกลุ่มสถานการณ์มักจะแย่กว่าการใช้คีย์ธรรมชาติที่มีขนาดเล็กที่สุด หากตารางถูกจัดเป็น heap ดังนั้น RowID ขนาด 8 ไบต์ (ฮีป) จะถูกใช้สำหรับการค้นหาคีย์ซึ่งดีกว่า GUID ขนาด 16 ไบต์ แต่มีประสิทธิภาพน้อยกว่าจำนวนเต็ม 4 ไบต์
หากต้องใช้ GUID เนื่องจากข้อ จำกัด ทางธุรกิจกว่าการค้นหาคีย์การทำคลัสเตอร์ที่ดีกว่านั้นคุ้มค่า หากตัวอย่างเช่นตัวระบุไซต์ขนาดเล็กและ 4 ไบต์ "ไซต์ลำดับหมายเลข" เป็นไปได้การออกแบบนั้นอาจให้ประสิทธิภาพที่ดีกว่า GUID ในฐานะตัวแทนคีย์
หากผลที่ตามมาของฮีป (อาจเข้าร่วมแฮช) ทำให้ที่เก็บข้อมูลที่ต้องการนั้นมีค่าใช้จ่ายของคีย์การจัดกลุ่มที่กว้างขึ้นจำเป็นต้องมีความสมดุลในการวิเคราะห์การแลกเปลี่ยน
ลองพิจารณาตัวอย่างนี้ ::
ALTER TABLE Persons
ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
โดยที่ tuple " (P_Id, LastName) " ต้องการข้อ จำกัด ที่ไม่ซ้ำกันและอาจเป็น Unicode LastName ที่มีความยาวและจำนวนเต็ม 4 ไบต์มันจะเป็นที่พึงปรารถนาที่จะ (1) ประกาศบังคับใช้ข้อ จำกัด นี้เป็น " ADD CONSTRAINT pk_PersonID UNIQUE , LastName) "และ (2) ประกาศคีย์ Surrogate ขนาดเล็กแยกเป็น" คีย์หลัก "ของดัชนีคลัสเตอร์ เป็นที่น่าสังเกตว่า Anita อาจต้องการเพิ่มนามสกุลในข้อ จำกัด นี้เท่านั้นเพื่อทำให้ฟิลด์ที่มีการครอบคลุมซึ่งไม่จำเป็นในดัชนีแบบคลัสเตอร์เนื่องจากฟิลด์ทั้งหมดถูกครอบคลุม
ความสามารถใน SQL Server เพื่อกำหนดคีย์หลักเป็น nonclustered เป็นสถานการณ์ทางประวัติศาสตร์ที่โชคร้ายเนื่องจากการ conflation ของความหมาย "คีย์ธรรมชาติหรือตัวเลือกที่ต้องการ" (จาก Logical Model) ที่มีความหมาย "คีย์การค้นหาในที่เก็บ" จาก Physical แบบ ความเข้าใจของฉันคือเดิมที SYBASE SQL Server มักใช้ RowID ขนาด 4 ไบต์ไม่ว่าจะเป็นฮีปหรือดัชนีคลัสเตอร์เป็น "คีย์การค้นหาในที่เก็บข้อมูล" จาก Physical Model
บางคนใช้คำว่า "คีย์หลัก" เพื่อหมายถึงคอลัมน์จำนวนเต็มที่ได้รับค่าที่สร้างขึ้นโดยกลไกอัตโนมัติบางอย่าง ตัวอย่างเช่นAUTO_INCREMENT
ใน MySQL หรือIDENTITY
ใน Microsoft SQL Server คุณใช้คีย์หลักในแง่นี้หรือไม่?
ถ้าเป็นเช่นนั้นคำตอบขึ้นอยู่กับยี่ห้อของฐานข้อมูลที่คุณใช้ ใน MySQL คุณไม่สามารถทำได้คุณได้รับข้อผิดพลาด:
mysql> create table foo (
id int primary key auto_increment,
id2 int auto_increment
);
ERROR 1075 (42000): Incorrect table definition;
there can be only one auto column and it must be defined as a key
ในฐานข้อมูลยี่ห้ออื่นคุณสามารถกำหนดคอลัมน์สร้างอัตโนมัติมากกว่าหนึ่งคอลัมน์ในตาราง
ไม่สามารถมีคีย์หลักสองตัวพร้อมกันได้ แต่ (สมมติว่าคุณไม่ได้ทำเรื่องยุ่งเหยิงด้วยคีย์คอมโพสิต) อาจเป็นสิ่งที่คุณอาจจำเป็นต้องมีเพื่อทำให้หนึ่งคุณลักษณะไม่ซ้ำกัน
CREATE t1(
c1 int NOT NULL,
c2 int NOT NULL UNIQUE,
...,
PRIMARY KEY (c1)
);
อย่างไรก็ตามโปรดทราบว่าในฐานข้อมูลเชิงสัมพันธ์ 'ซุปเปอร์คีย์' เป็นชุดย่อยของคุณลักษณะที่ระบุทูเปิลหรือแถวในตารางโดยไม่ซ้ำกัน A 'key' คือ 'super key' ที่มีคุณสมบัติเพิ่มเติมที่ลบแอตทริบิวต์ใด ๆ ออกจากคีย์ทำให้ key นั้นไม่ต้องเป็น 'super key' อีกต่อไป (หรือเพียงแค่ 'key' เป็น super key ที่น้อยที่สุด) หากมีปุ่มเพิ่มเติมกุญแจทั้งหมดจะเป็นปุ่มตัวเลือก เราเลือกหนึ่งในกุญแจผู้สมัครเป็นคีย์หลัก นั่นเป็นเหตุผลที่พูดถึงคีย์หลักหลาย ๆ อันสำหรับความสัมพันธ์หรือตารางหนึ่งกำลังขัดแย้งกัน
คีย์หลักคือคีย์ที่ระบุระเบียนและใช้ในดัชนีทั้งหมด นี่คือเหตุผลที่คุณไม่สามารถมีมากกว่าหนึ่ง นอกจากนี้ยังเป็นกุญแจสำคัญที่ใช้ในการเข้าร่วมตารางลูก แต่นี่ไม่ใช่ข้อกำหนด วัตถุประสงค์ที่แท้จริงของ PK คือเพื่อให้แน่ใจว่าสิ่งที่ช่วยให้คุณสามารถระบุระเบียนเพื่อให้การเปลี่ยนแปลงข้อมูลมีผลต่อระเบียนที่ถูกต้องและเพื่อให้สามารถสร้างดัชนีได้
อย่างไรก็ตามคุณสามารถใส่หลายฟิลด์ในคีย์หลักเดียว (คอมโพสิต PK) สิ่งนี้จะทำให้การรวมของคุณช้าลง (โดยเฉพาะถ้ามันเป็นเขตข้อมูลชนิดสตริงขนาดใหญ่) และดัชนีของคุณมีขนาดใหญ่ขึ้น แต่มันอาจลบความจำเป็นในการเข้าร่วมในตารางลูกบางส่วนดังนั้นเท่าที่ประสิทธิภาพและการออกแบบ กรณีพื้นฐาน เมื่อคุณทำเช่นนี้แต่ละฟิลด์จะไม่ซ้ำกัน แต่เป็นการรวมกันของฟิลด์เหล่านั้น หากหนึ่งหรือมากกว่าหนึ่งฟิลด์ในคีย์ผสมควรเป็นค่าเฉพาะดังนั้นคุณต้องมีดัชนีที่ไม่ซ้ำกัน อาจเป็นไปได้ว่าหากมีหนึ่งเขตข้อมูลที่ไม่ซ้ำกันนี่เป็นตัวเลือกที่ดีกว่าสำหรับ PK
ในบางครั้งคุณมีผู้สมัครมากกว่าหนึ่งคนสำหรับ PK ในกรณีนี้คุณเลือกหนึ่งตัวเป็น PK หรือใช้คีย์ตัวแทน (โดยส่วนตัวแล้วฉันชอบคีย์ตัวแทนสำหรับอินสแตนซ์นี้) และ (นี่เป็นสิ่งสำคัญ!) คุณเพิ่มดัชนีที่ไม่ซ้ำกันให้กับแต่ละปุ่มตัวเลือกที่ไม่ได้รับเลือกให้เป็น PK หากข้อมูลต้องไม่ซ้ำกันจะต้องมีดัชนีเฉพาะไม่ว่าจะเป็น PK หรือไม่ นี่เป็นปัญหาด้านความสมบูรณ์ของข้อมูล (โปรดทราบว่านี่เป็นความจริงทุกครั้งที่คุณใช้คีย์ตัวแทนซึ่งผู้คนจะมีปัญหากับคีย์ตัวแทนเนื่องจากพวกเขาลืมที่จะสร้างดัชนีที่ไม่ซ้ำกันในคีย์ตัวเลือก)
มีบางครั้งเมื่อคุณต้องการคีย์ตัวแทนมากกว่าหนึ่งคีย์ (ซึ่งมักจะเป็น PK หากคุณมีพวกเขา) ในกรณีนี้สิ่งที่คุณต้องการไม่ใช่ของ PK มากขึ้นมันคือฟิลด์ที่มีคีย์ที่สร้างอัตโนมัติ ฐานข้อมูลส่วนใหญ่ไม่อนุญาตให้ทำเช่นนี้ แต่มีวิธีการรับรอบ ก่อนอื่นให้พิจารณาว่าเขตข้อมูลที่สองสามารถคำนวณได้จากคีย์ที่สร้างอัตโนมัติครั้งแรก (Field1 * -1 เป็นต้น) หรืออาจเป็นความต้องการของคีย์ที่สร้างอัตโนมัติตัวที่สองหมายความว่าคุณควรสร้างตารางที่เกี่ยวข้อง ตารางที่เกี่ยวข้องสามารถอยู่ในความสัมพันธ์แบบหนึ่งต่อหนึ่ง คุณจะบังคับใช้โดยการเพิ่ม PK จากตารางพาเรนต์ไปยังตารางชายด์จากนั้นเพิ่มฟิลด์ที่สร้างอัตโนมัติใหม่ลงในตารางจากนั้นฟิลด์ใดก็ได้ที่เหมาะสมสำหรับตารางนี้ จากนั้นเลือกหนึ่งในสองคีย์เป็น PK และวางดัชนีเฉพาะลงบนอีกอันหนึ่ง (ฟิลด์ที่สร้างอัตโนมัติไม่จำเป็นต้องเป็น PK) และตรวจสอบให้แน่ใจว่าได้เพิ่ม FK ไปยังเขตข้อมูลที่อยู่ในตารางหลัก โดยทั่วไปหากคุณไม่มีฟิลด์เพิ่มเติมสำหรับตารางลูกคุณต้องตรวจสอบว่าทำไมคุณถึงคิดว่าคุณต้องการสองฟิลด์ที่สร้างอัตโนมัติ
คำตอบทางเทคนิคที่ดีได้รับในวิธีที่ดีกว่าที่ฉันสามารถทำได้ ฉันสามารถเพิ่มไปยังหัวข้อนี้เท่านั้น:
หากคุณต้องการบางสิ่งที่ไม่ได้รับอนุญาต / ยอมรับมันเป็นเหตุผลที่ดีที่จะก้าวถอยหลัง
หวังว่ามันจะช่วยใครซักคน
ใช่เป็นไปได้ใน SQL แต่เราไม่สามารถตั้งค่าคีย์หลักได้มากกว่าหนึ่งคีย์ใน MsAccess จากนั้นฉันไม่รู้เกี่ยวกับฐานข้อมูลอื่น
CREATE TABLE CHAPTER (
BOOK_ISBN VARCHAR(50) NOT NULL,
IDX INT NOT NULL,
TITLE VARCHAR(100) NOT NULL,
NUM_OF_PAGES INT,
PRIMARY KEY (BOOK_ISBN, IDX)
);