Lý do điều này khiến bạn cảm thấy kỳ lạ là bạn đang nghĩ về số gia tăng trên bộ đếm như một phần của thao tác chèn, và do đó, "DO NOTHING" phải có nghĩa là "không tăng bất cứ điều gì". Bạn đang hình dung thế này:
- Kiểm tra các giá trị cần chèn để chống lại sự ràng buộc
- Nếu phát hiện trùng lặp, hãy hủy bỏ
- Trình tự tăng dần
- Chèn dữ liệu
Nhưng trên thực tế, sự gia tăng phải xảy ra trước khi thử chèn . Một SERIAL
cột trong Postgres được triển khai dưới dạng DEFAULT
thực thi nextval()
chức năng trên một SEQUENCE
được ràng buộc . Trước khi DBMS có thể làm bất cứ điều gì với dữ liệu, nó phải có một tập hợp các cột hoàn chỉnh, vì vậy thứ tự của các hoạt động như sau:
- Giải quyết các giá trị mặc định, bao gồm cả việc tăng trình tự
- Kiểm tra các giá trị cần chèn để chống lại sự ràng buộc
- Nếu phát hiện trùng lặp, hãy hủy bỏ
- Chèn dữ liệu
Điều này có thể được nhìn thấy một cách trực quan nếu khóa trùng lặp nằm trong chính trường autoincrement:
CREATE TABLE foo ( id SERIAL NOT NULL PRIMARY KEY, bar text );
-- Insert row 1
INSERT INTO foo ( bar ) VALUES ( 'test' );
-- Reset the sequence
SELECT setval(pg_get_serial_sequence('foo', 'id'), 0, true);
-- Attempt to insert row 1 again
INSERT INTO foo ( bar ) VALUES ( 'test 2' )
ON CONFLICT (id) DO NOTHING;
Rõ ràng, điều này không thể biết nếu có xung đột nếu không tăng trình tự, vì vậy "không làm gì" phải đến sau gia số đó.