SQLite có một cách thú vị để xử lý các cột tăng tự động. Bằng cách tự động tăng cột, ý tôi là các cột tự động tăng lên bất cứ khi nào dữ liệu mới được chèn vào.
Điều này tương tự với IDENTITY
trong SQL Server hoặc AUTO_INCREMENT
trong MySQL
.
Bài viết này giải thích cách tạo AUTOINCREMENT
các cột trong SQLite.
Tự động tạo cột Tự động tăng dần
Theo mặc định, khi bạn xác định một cột là INTEGER PRIMARY KEY
, nó sẽ tự động tăng lên bất cứ khi nào bạn chèn NULL vào cột đó.
Ví dụ:
CREATE TABLE Cats(
CatId INTEGER PRIMARY KEY,
CatName
);
Trong bảng này, CatId là một cột tự động tăng. Điều này là do nó đã được xác định bằng cách sử dụng INTEGER PRIMARY KEY
.
Bây giờ, khi tôi chèn NULL vào cột đó, CatId cột tăng tự động:
INSERT INTO Cats VALUES
( NULL, 'Brush' ),
( NULL, 'Scarcat' ),
( NULL, 'Flutter' );
SELECT * FROM Cats;
Kết quả:
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 Flutter
Điều quan trọng cần lưu ý là bạn có thể ghi đè AUTOINCREMENT
giá trị bằng cách chèn giá trị của riêng bạn. Nói cách khác, AUTOINCREMENT
chỉ chèn một giá trị nếu bạn không chèn.
Cách thức hoạt động là NULL
được tự động chuyển đổi thành một số nguyên lớn hơn một giá trị lớn nhất của cột đó trên tất cả các hàng khác trong bảng. Nếu bảng trống, giá trị sẽ là 1
.
Nếu giá trị lớn nhất của cột là số nguyên lớn nhất có thể (9223372036854775807), thì SQLite sẽ chọn ngẫu nhiên một khóa không sử dụng. Điều này thường có nghĩa là nó sẽ sử dụng lại các khóa cũ đã bị xóa trước đó. Nếu không tìm thấy khóa không sử dụng, hãy INSERT
hoạt động không thành công với một SQLITE_FULL
lỗi.
Về cơ bản, điều này có nghĩa là gì, nếu bạn cho phép DELETE
các thao tác trong bảng thì không có gì đảm bảo rằng tất cả các hàng sẽ theo thứ tự. Có khả năng một số hàng sẽ có giá trị cao hơn các hàng được chèn vào một ngày sau đó.
Do đó, trong những trường hợp như vậy, bạn không thể dựa vào cột này nếu bạn cần sắp xếp bảng theo thứ tự tăng dần hoặc giảm dần, dựa trên thứ tự mà các hàng đã được chèn.
May mắn thay, nếu đây là vấn đề với bạn, có một giải pháp:AUTOINCREMENT
từ khóa.
Sử dụng Từ khóa AUTOINCREMENT
Ngoài ra, bạn có thể chọn đặt cột thành tự động tăng dần một cách rõ ràng bằng cách sử dụng AUTOINCREMENT
từ khóa.
Một lợi ích của việc sử dụng phương pháp này là nó đảm bảo rằng tất cả các hàng sẽ theo thứ tự tăng dần. Điều này là do nó không sử dụng lại các khóa đã xóa trước đó. Mỗi khóa sẽ luôn nhiều hơn một khóa lớn nhất đã từng tồn tại trong bảng đó. Nếu khóa lớn nhất có thể đã tồn tại trước đó trong bảng đó thì khóa đó sẽ không cố gắng sử dụng các khóa đã xóa trước đó. INSERT
sẽ không thành công với một SQLITE_FULL
mã lỗi.
Nhược điểm của việc sử dụng AUTOINCREMENT
từ khóa là nó sử dụng thêm CPU, bộ nhớ, không gian đĩa và chi phí I / O đĩa.
Dưới đây là ví dụ về cách tạo cột tự động tăng dần với AUTOINCREMENT
từ khóa:
CREATE TABLE Dogs(
DogId INTEGER PRIMARY KEY AUTOINCREMENT,
DogName
);
Bây giờ hãy chèn dữ liệu và chọn nó:
INSERT INTO Dogs VALUES
( NULL, 'Yelp' ),
( NULL, 'Woofer' ),
( NULL, 'Fluff' );
SELECT * FROM Dogs;
Kết quả:
DogId DogName ---------- ---------- 1 Yelp 2 Woofer 3 Fluff
Nếu tôi xóa Fluff từ bảng này, sau đó chèn một hàng mới (sử dụng NULL
như DogId), DogId mới sẽ là 4. Nói cách khác, nó sẽ không sử dụng lại 3.
Nếu cột đã được tạo không có AUTOINCREMENT
từ khóa, thì hàng tiếp theo sẽ sử dụng lại DogId của 3.
Nếu tôi phải chèn DogId là 9223372036854775807 (số nguyên lớn nhất có thể), tôi sẽ nhận được lỗi sau khi chèn tiếp theo chỉ định NULL
cho cột đó:
Error: database or disk is full
Tuy nhiên, tôi có thể chèn một cách rõ ràng giá trị thấp hơn 9223372036854775807, miễn là giá trị đó chưa được hàng khác và INSERT
sử dụng hoạt động sẽ thành công mà không có lỗi ở trên.
Về cơ bản, khi bạn đạt đến 9223372036854775807, tính năng tự động tăng sẽ không hoạt động nữa.
Các cột được xác định mà không có AUTOINCREMENT
từ khóa không có vấn đề này. Họ sẽ tự động quay lại và cố gắng tìm một số nguyên không sử dụng để sử dụng thay thế. Tuy nhiên, nếu tất cả các số nguyên đã được sử dụng (tức là bảng thực sự chứa 9223372036854775807 hàng), thì ngay cả các cột đó cũng sẽ dẫn đến lỗi trên.