คีย์หลักของ sqlite ในหลายคอลัมน์


619

ไวยากรณ์สำหรับการระบุคีย์หลักในคอลัมน์มากกว่า 1 คอลัมน์ใน SQLITE คืออะไร


14
นี่เรียกอีกอย่างว่าคีย์ผสมen.wikipedia.org/wiki/Compound_key
OneWorld

6
@OneWorld หรือคีย์ผสมถ้ามีคอลัมน์ใด ๆ ไม่ใช่คีย์ตัวเอง
Michael

คำตอบ:


805

ตามเอกสารประกอบนั้น

CREATE TABLE something (
  column1, 
  column2, 
  column3, 
  PRIMARY KEY (column1, column2)
);

3
ทีนี้นี่ถูกต้อง แต่ตามเอกสารประกอบ CREATE TABLE บางอย่าง (column1 Primary KEY, column2 primary KEY); ควรเป็นไปได้เช่นกัน แต่ไม่เป็นเช่นนั้น
Yar

6
@Yar เอกสารพูดว่า "หากมีคีย์หลักมากกว่าหนึ่งประโยคในคำสั่ง CREATE TABLE เดียวมันเป็นข้อผิดพลาด" ใช่ไดอะแกรมทางรถไฟอาจบ่งบอกว่าถูกต้องเช่นกัน แต่ข้อความด้านล่างชี้แจงว่าไม่ถูกต้อง
Brian Campbell

10
อย่าลืมเพิ่มคีย์หลัก (คอลัมน์ 1, คอลัมน์ 2)ที่ท้ายเหมือนในคำตอบนี้ ถ้าคุณพยายามที่จะเพิ่มความคมชัดหลังจาก column2 คุณจะได้รับข้อผิดพลาดทางไวยากรณ์
vovahost

159
CREATE TABLE something (
  column1 INTEGER NOT NULL,
  column2 INTEGER NOT NULL,
  value,
  PRIMARY KEY ( column1, column2)
);

คีย์หลักไม่กำหนดค่าเป็น NULL หรือไม่
pratnala

23
@pratnala ใน SQL มาตรฐานใช่ ใน SQLite NULLอนุญาตให้ใช้ในคีย์หลัก คำตอบนี้เน้นว่าหากคุณต้องการพฤติกรรมมาตรฐานมากขึ้นคุณต้องเพิ่มNOT NULLตัวเอง คำตอบของฉันเป็นเพียงไวยากรณ์พื้นฐานที่สำคัญสำหรับคีย์หลักหลายคอลัมน์
Brian Campbell

42

ใช่. แต่โปรดจำไว้ว่าคีย์หลักดังกล่าวอนุญาตให้มีNULLค่าในทั้งสองคอลัมน์หลายครั้ง

สร้างตารางเช่น:

    sqlite> CREATE TABLE something (
column1, column2, value, PRIMARY KEY (column1, column2));

ตอนนี้ใช้ได้โดยไม่มีการเตือนล่วงหน้า:

sqlite> insert into something (value) VALUES ('bla-bla');
sqlite> insert into something (value) VALUES ('bla-bla');
sqlite> select * from something;
NULL|NULL|bla-bla
NULL|NULL|bla-bla

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

4
@Pastafarianist sqlite.org/lang_createtable.html - "ตามมาตรฐาน SQL คีย์หลักควรบอกเป็นนัยว่าไม่เป็นโมฆะโชคไม่ดีเนื่องจากข้อผิดพลาดในบางเวอร์ชันก่อนหน้านี้ไม่ใช่กรณีใน SQLite [... ] NULL ค่าจะถือว่าแตกต่างจากค่าอื่น ๆ ทั้งหมดรวมถึง NULL อื่น ๆ "
เหลือเชื่อ

ใช่ใน SQL NULL จะเปรียบเทียบ false เสมอ ด้วยเหตุนี้ทฤษฎีเชิงสัมพันธ์จึงไม่รวมค่า NULL เป็นค่าขององค์ประกอบหลักใด ๆ อย่างไรก็ตาม SQLite เป็นแนวปฏิบัติที่สัมพันธ์กัน ดูเหมือนว่าผู้เขียนเลือกที่จะอนุญาตให้ใช้กุญแจหลาย ๆ ปุ่ม แต่ไม่ได้ "เท่ากัน" ในทางปฏิบัติ เห็นได้ชัดว่าเป็นการดีที่จะไม่อนุญาตให้ NULL เป็นค่าคีย์
holdenweb

31

ขั้นพื้นฐาน :

CREATE TABLE table1 (
    columnA INTEGER NOT NULL,
    columnB INTEGER NOT NULL,
    PRIMARY KEY (columnA, columnB)
);

หากคอลัมน์ของคุณเป็นรหัสต่างประเทศของตารางอื่น ๆ (กรณีทั่วไป):

CREATE TABLE table1 (
    table2_id INTEGER NOT NULL,
    table3_id INTEGER NOT NULL,
    FOREIGN KEY (table2_id) REFERENCES table2(id),
    FOREIGN KEY (table3_id) REFERENCES table3(id),
    PRIMARY KEY (table2_id, table3_id)
);

CREATE TABLE table2 (
    id INTEGER NOT NULL,
    PRIMARY KEY id
);

CREATE TABLE table3 (
    id INTEGER NOT NULL,
    PRIMARY KEY id
);

14

เขตข้อมูลคีย์หลักควรประกาศเป็นไม่เป็นโมฆะ (นี่ไม่ใช่มาตรฐานตามคำจำกัดความของคีย์หลักคือต้องไม่ซ้ำกันและไม่เป็นค่าว่าง) แต่ด้านล่างเป็นแนวปฏิบัติที่ดีสำหรับคีย์หลักหลายคอลัมน์ใน DBMS ใด ๆ

create table foo
(
  fooint integer not null
  ,foobar string not null
  ,fooval real
  ,primary key (fooint, foobar)
)
;

11

ตั้งแต่เวอร์ชัน 3.8.2 ของ SQLite ทางเลือกอื่นสำหรับข้อมูลจำเพาะ NOT NULL ที่ชัดเจนคือข้อกำหนด "โดยไม่ต้องรอ": [ 1 ]

NOT NULL is enforced on every column of the PRIMARY KEY
in a WITHOUT ROWID table.

ตาราง "โดยไม่ต้องรอ" มีข้อได้เปรียบด้านประสิทธิภาพที่อาจเกิดขึ้นดังนั้นทางเลือกที่ละเอียดน้อยกว่าในการพิจารณาคือ:

CREATE TABLE t (
  c1, 
  c2, 
  c3, 
  PRIMARY KEY (c1, c2)
 ) WITHOUT ROWID;

ตัวอย่างเช่นที่พรอมต์ sqlite3: sqlite> insert into t values(1,null,3); Error: NOT NULL constraint failed: t.c2


สำหรับทุกคนที่อ่านวันนี้: WITHOUT ROWIDมีความหมายเพิ่มเติมและไม่ควรใช้เป็นทางเลือกในการเขียนNOT NULLถัดจากคีย์หลักของคุณ
shadowtalker

2

ในอีกทางหนึ่งนอกจากนี้คุณยังสามารถทำให้สองคอลัมน์คีย์หลัก uniqueและเพิ่มโดยอัตโนมัติprimaryที่สำคัญ แบบนี้: https://stackoverflow.com/a/6157337


นี่คือสิ่งที่ฉันมองหาอย่างแน่นอน ขอบคุณ!
Swadhikar C

2

PRIMARY KEY (id, name)ไม่ได้ผลสำหรับฉัน การเพิ่มข้อ จำกัด ทำงานแทน

CREATE TABLE IF NOT EXISTS customer (id INTEGER, name TEXT, user INTEGER, CONSTRAINT PK_CUSTOMER PRIMARY KEY (user, id))


1

รหัสต่อไปนี้สร้างตารางที่มี2 คอลัมน์เป็นคีย์หลักใน SQLite

สารละลาย:

CREATE TABLE IF NOT EXISTS users (id TEXT NOT NULL, name TEXT NOT NULL, pet_name TEXT, PRIMARY KEY (id, name))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.