มีการเพิ่มอัตโนมัติใน sqlite หรือไม่?


109

ฉันพยายามที่จะสร้างตารางที่มีอัตโนมัติที่เพิ่มขึ้นprimary keyในSqlite3 ฉันไม่แน่ใจว่าเป็นไปได้จริงหรือไม่ แต่ฉันหวังว่าจะต้องกำหนดช่องอื่นเท่านั้น

ตัวอย่างเช่น:

CREATE TABLE people (id integer primary key auto increment, first_name varchar(20), last_name varchar(20));

จากนั้นเมื่อฉันเพิ่มมูลค่าฉันหวังว่าจะต้องทำเท่านั้น:

INSERT INTO people
VALUES ("John", "Smith");

เป็นไปได้หรือไม่?

ฉันกำลังทำงานsqlite3ภายใต้cygwinWindows 7

คำตอบ:


167

คุณจะได้รับฟรีที่เรียกว่า ROWID นี่คือในทุกตาราง SQLite ไม่ว่าคุณจะขอหรือไม่ก็ตาม

หากคุณรวมคอลัมน์ประเภท INTEGER PRIMARY KEY คอลัมน์นั้นจะชี้ที่ (เป็นนามแฝงสำหรับ) คอลัมน์ ROWID อัตโนมัติ

ROWID (ตามชื่อที่คุณเรียก) จะได้รับการกำหนดค่าทุกครั้งที่คุณใส่แถวตามที่คุณคาดหวัง หากคุณกำหนดค่าที่ไม่ใช่ NULL อย่างชัดเจนใน INSERT ค่านั้นจะได้รับค่าที่ระบุแทนการเพิ่มอัตโนมัติ หากคุณกำหนดค่าเป็น NULL บน INSERT อย่างชัดเจนก็จะได้รับค่าการเพิ่มอัตโนมัติถัดไป

นอกจากนี้คุณควรพยายามหลีกเลี่ยง:

 INSERT INTO people VALUES ("John", "Smith");

และใช้

 INSERT INTO people (first_name, last_name) VALUES ("John", "Smith");

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


53
ROWID ไม่เหมือนกับการเพิ่มอัตโนมัติจริงเนื่องจากอาจมีการสร้างค่า SAME มากกว่าหนึ่งครั้ง ตัวอย่างเช่นด้วยตารางว่างการแทรก 3 แถวจะทำให้แถวที่ 3 มี ROWID เป็น 3 ตามที่คาดไว้ อย่างไรก็ตามแทรก 2 แถวลบสุดท้ายและแทรกอีกทำให้แถวที่ 3 แทรก ROWID เป็น 2 เช่นเดียวกับแถวที่ 2 มี ดังนั้นจึงมีปัญหาร้ายแรงที่เห็นได้ชัดหากตารางอ้างอิง ROWID ในตารางที่การลบเกิดขึ้นและจุดที่การลบหรือการลบ ROWID ไม่ได้กระทำในตารางที่เกี่ยวข้อง
Nick

10
ในกรณีที่ไม่ชัดเจนจากคำตอบคุณสามารถใช้ ROWID ในคำสั่งที่คุณเลือกเช่นselect rowid from people;
Colin D

@ เพียงแค่เติมเต็มความคิดของคุณ: การเพิ่มอัตโนมัติจึงเป็นมาตรการด้านความปลอดภัย และเราไม่ได้พูดถึงสองแถวที่ชนกันใน ROWID
YoussefDir

70

ใช่มันเป็นไปได้ ตามคำถามที่พบบ่อยของ SQLite :

คอลัมน์ที่ประกาศINTEGER PRIMARY KEYจะสร้างอัตโนมัติ


12
ข้อแม้ดังที่ Uku กล่าวถึงและยังได้อธิบายไว้ในเอกสารคือคุณต้องส่งรหัสเป็น NULL จึงจะสามารถใช้งานได้
Matt Hulse

22
คุณจะต้องใช้ค่า NULL หากคุณไม่ต้องใส่รายการคอลัมน์เพื่อ INSERT - ไม่ใช่แนวทางปฏิบัติที่ดี หากคุณระบุคอลัมน์คุณสามารถละทิ้งคอลัมน์ที่เพิ่มขึ้นอัตโนมัติและจะได้รับค่าถัดไป
Larry Lustig

5
ข้อแม้อีกประการ: เขียน "INTEGER ... " ตามที่ระบุไว้ข้างต้น ชวเลข "INT ... " จะไม่ทำงาน
Marcin Wojnarski

27

ณ วันนี้ - มิถุนายน 2561


นี่คือสิ่งที่เอกสาร SQLite อย่างเป็นทางการกล่าวถึงในหัวข้อนี้ (ตัวหนาและตัวเอียงเป็นของฉัน):

  1. AUTOINCREMENTคำหลักที่มีการเรียกเก็บ CPU เสริมหน่วยความจำพื้นที่ดิสก์และดิสก์ของ I / O ค่าใช้จ่ายและควรหลีกเลี่ยงถ้าไม่จำเป็นต้องเคร่งครัด มักไม่จำเป็น

  2. ใน SQLite คอลัมน์ที่มีประเภทINTEGER PRIMARY KEY เป็นนามแฝงสำหรับ ROWID (ยกเว้นในตาราง WITHOUT ROWID) ซึ่งจะเป็นเลขจำนวนเต็ม 64 บิตเสมอ

  3. ใน INSERT ถ้าคอลัมน์ ROWID หรือ INTEGER PRIMARY KEY ไม่ได้ ระบุค่าไว้อย่างชัดเจนค่านั้นจะถูกเติมโดยอัตโนมัติด้วย จำนวนเต็มที่ไม่ได้ใช้โดยปกติจะเป็นมากกว่า ROWID ที่ใหญ่ที่สุดที่ ใช้อยู่ในปัจจุบัน สิ่งนี้เป็นจริงไม่ว่าจะใช้คีย์เวิร์ด AUTOINCREMENT หรือไม่ก็ตาม

  4. หากคีย์เวิร์ดAUTOINCREMENTปรากฏขึ้นหลัง INTEGER PRIMARY KEYนั่นจะเป็นการเปลี่ยนอัลกอริทึมการกำหนด ROWID อัตโนมัติเพื่อป้องกันการนำ ROWID มาใช้ซ้ำตลอดอายุการใช้งานของฐานข้อมูล กล่าวอีกนัยหนึ่งวัตถุประสงค์ของ AUTOINCREMENT คือการป้องกันการนำ ROWID มาใช้ซ้ำจากแถวที่ลบไปก่อนหน้านี้


11

คุณอ่านสิ่งนี้แล้วหรือยัง? ฉันจะสร้างฟิลด์ AUTOINCREMENT ได้อย่างไร

INSERT INTO people
VALUES (NULL, "John", "Smith");

สิ่งที่คุณกำลังพูดคือสิ่งที่ฉันพยายามทำนั้นเป็นไปไม่ได้ แต่ฉันสามารถจำลองได้ ฉันต้องใช้ null ในการแทรก?
ewok

1
คุณไม่จำเป็นต้องทำอะไรเลย แต่จะใส่ NULL เป็น id เสมอมันอธิบายว่า sqlite ทำอย่างไรภายใน
Uku Loskit

7
จำเป็นต้องใช้NULL บน INSERT ก็ต่อเมื่อคุณไม่ได้ระบุรายการคอลัมน์ที่จะ INSERT (ในกรณีนี้คุณต้องมีค่าจำนวนหนึ่งที่ตรงกับจำนวนคอลัมน์และต้องใช้ NULL เป็นตัวยึด) แต่การทำ INSERT โดยไม่ระบุรายการคอลัมน์ไม่ใช่แนวทางปฏิบัติที่ดี หากคุณระบุรายการคอลัมน์เพียงแค่เว้นทั้งคอลัมน์การสร้างอัตโนมัติและค่า NULL แล้วคุณจะได้ผลลัพธ์ตามที่คุณคาดหวัง
Larry Lustig

4

หนึ่งไม่ควรระบุคำหลักที่อยู่ใกล้AUTOINCREMENT PRIMARY KEYตัวอย่างการสร้างคีย์หลักและการแทรกอัตโนมัติ:

$ sqlite3 ex1

CREATE TABLE IF NOT EXISTS room(room_id INTEGER PRIMARY KEY, name VARCHAR(25) NOT NULL, home_id VARCHAR(25) NOT NULL);

INSERT INTO room(name, home_id) VALUES ('test', 'home id test');

INSERT INTO room(name, home_id) VALUES ('test 2', 'home id test 2');

SELECT * FROM room;

จะให้:

1|test|home id test
2|test 2|home id test 2

4

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

AUTOINCREMENTเรียกเก็บคำหลัก CPU เสริมหน่วยความจำพื้นที่ดิสก์และดิสก์ของ I / O ค่าใช้จ่ายและควรหลีกเลี่ยงถ้าไม่จำเป็นต้องเคร่งครัด มักไม่จำเป็น

อ่านรายละเอียดได้ที่นี่


เห็นได้ชัดว่า rowid ไม่ได้เพิ่มขึ้นโดยอัตโนมัติเสมอไปดูความคิดเห็นของ Nick
rogerdpack

1
ไม่จริง. การเพิ่มอัตโนมัติจะดีกว่าในบางประเด็นเนื่องจากจะไม่นำรหัสมาใช้ซ้ำซึ่งเป็นข้อกำหนดที่สำคัญมากสำหรับระบบต่างๆ
O'Rooney

4

SQLite AUTOINCREMENT คือคีย์เวิร์ดที่ใช้สำหรับการเพิ่มค่าของฟิลด์ในตารางโดยอัตโนมัติ เราสามารถเพิ่มค่าฟิลด์อัตโนมัติโดยใช้คำสำคัญอัตโนมัติเมื่อสร้างตารางที่มีชื่อคอลัมน์เฉพาะเพื่อเพิ่มค่าอัตโนมัติ

คำสำคัญ AUTOINCREMENT สามารถใช้ได้กับฟิลด์ INTEGER เท่านั้น ไวยากรณ์:

การใช้งานคีย์เวิร์ด AUTOINCREMENT พื้นฐานมีดังนี้:

CREATE TABLE table_name(
   column1 INTEGER AUTOINCREMENT,
   column2 datatype,
   column3 datatype,
   .....
   columnN datatype,
);

ตัวอย่างดูด้านล่าง: พิจารณาตาราง COMPANY ที่จะสร้างดังต่อไปนี้:

sqlite> CREATE TABLE TB_COMPANY_INFO(
   ID INTEGER PRIMARY KEY   AUTOINCREMENT,
   NAME           TEXT      NOT NULL,
   AGE            INT       NOT NULL,
   ADDRESS        CHAR(50),
   SALARY         REAL
);

ตอนนี้แทรกระเบียนต่อไปนี้ในตาราง TB_COMPANY_INFO:

INSERT INTO TB_COMPANY_INFO (NAME,AGE,ADDRESS,SALARY)
VALUES ( 'MANOJ KUMAR', 40, 'Meerut,UP,INDIA', 200000.00 );

ตอนนี้เลือกบันทึก

SELECT *FROM TB_COMPANY_INFO
ID      NAME            AGE     ADDRESS             SALARY
1       Manoj Kumar     40      Meerut,UP,INDIA     200000.00

2

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

ตอนนี้เมื่อมองย้อนกลับไปที่คำถามของคุณมันควรจะเป็นแบบนี้

CREATE TABLE people (id integer primary key autoincrement, first_name varchar(20), last_name varchar(20));

มันได้ผลในตอนท้ายของฉัน เช่นนั้น

ป้อนคำอธิบายภาพที่นี่

ในกรณีที่คุณกำลังทำงานกับ SQLite ผมขอแนะนำให้คุณตรวจสอบฐานข้อมูลเบราว์เซอร์สำหรับ SQLite ทำงานบนแพลตฟอร์มที่แตกต่างกันเช่นกัน


0

สิ่งที่คุณทำนั้นถูกต้อง แต่ไวยากรณ์ที่ถูกต้องสำหรับ "การเพิ่มอัตโนมัติ" ควรไม่มีช่องว่าง:

CREATE TABLE people (id integer primary key autoincrement, first_name string, last_name string);

(โปรดทราบว่าฉันเปลี่ยน varchars ของคุณเป็นสตริงนั่นเป็นเพราะ SQLite แปลง varchar เป็นสตริงภายในดังนั้นทำไมต้องกังวล?)

จากนั้นส่วนแทรกของคุณควรเป็นภาษา SQL ตามมาตรฐานที่สุด:

INSERT INTO people(id, first_name, last_name) VALUES (null, 'john', 'doe');

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

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

HTH


ในแง่นี้ฉันแบ่งปันสิ่งที่ O'Rooney พูดโดยสิ้นเชิง
Luca Nanetti

และถ้าคุณพยายามทำเครื่องหมายในช่อง AI ใน DB Browser สำหรับไดอะล็อก Modify Table ของ SQLite มันจะไม่บันทึกว่าถ้ามีเรกคอร์ดในตารางอยู่แล้ว วิธีแก้ปัญหาของฉันคือทำการส่งออก "ทุกอย่าง" และแก้ไขข้อกำหนดของไฟล์. sql ของ PK เพื่อเพิ่ม AUTOINCREMENT จากนั้นใช้ไฟล์นั้นเพื่อนำเข้ากลับไปที่ฐานข้อมูล ไม่เพียง แต่รักษา AI แต่ยังรักษาค่า PK ไว้เหมือนเดิมแม้ว่าจะไม่ได้เริ่มที่ 1
Mike V
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.