SQLite
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> SQLite

Xử lý xung đột khóa chính khi chèn dữ liệu vào SQLite

SQLite có một mệnh đề mở rộng SQL không chuẩn được gọi là ON CONFLICT cho phép chúng tôi chỉ định cách giải quyết các xung đột ràng buộc.

Đặc biệt, điều khoản áp dụng cho UNIQUE , NOT NULL , CHECKPRIMARY KEY ràng buộc.

Bài viết này cung cấp các ví dụ về cách mệnh đề này có thể được sử dụng để xác định cách xử lý xung đột ràng buộc khóa chính.

"Xung đột ràng buộc khóa chính", ý tôi là khi bạn cố gắng chèn một giá trị trùng lặp vào cột khóa chính. Theo mặc định, khi bạn cố gắng thực hiện việc này, hoạt động sẽ bị hủy bỏ và SQLite sẽ trả về lỗi.

Nhưng bạn có thể sử dụng ON CONFLICT để thay đổi cách SQLite giải quyết những tình huống này.

Một tùy chọn là sử dụng mệnh đề này trong CREATE TABLE khi tạo bảng. Làm điều đó sẽ xác định cách tất cả INSERT các hoạt động được xử lý.

Một tùy chọn khác là sử dụng mệnh đề trên INSERT câu lệnh bất cứ khi nào bạn cố gắng chèn dữ liệu vào bảng. Điều này cho phép bạn tận dụng điều khoản ngay cả khi bảng không được tạo với nó. Khi bạn sử dụng tùy chọn này, cú pháp sẽ khác; bạn sử dụng OR thay vì ON CONFLICT .

Các ví dụ trên trang này sử dụng tùy chọn thứ hai - Tôi tạo bảng không có ON CONFLICT và thay vào đó tôi chỉ định OR trên INSERT tuyên bố.

Bảng mẫu

Hãy tạo một bảng đơn giản và thêm một hàng.

CREATE TABLE Products( 
    ProductId INTEGER PRIMARY KEY, 
    ProductName, 
    Price
);

INSERT INTO Products VALUES (1, 'Hammer', 8.00);

SELECT * FROM Products;

Kết quả:

ProductId   ProductName  Price     
----------  -----------  ----------
1           Hammer       8.0       

Chúng tôi hiện có một hàng, với ProductId trong tổng số 1 .

Bây giờ chúng ta có thể chạy qua các tình huống khác nhau của việc chèn dữ liệu vào bảng đó vi phạm giới hạn khóa chính.

Ví dụ 1 - Hủy bỏ (Hành vi mặc định)

Như đã đề cập, hành vi mặc định cho SQLite là hủy bỏ INSERT hoạt động và trả về lỗi.

INSERT INTO Products VALUES (1, 'Wrench', 12.50);

Kết quả:

Error: UNIQUE constraint failed: Products.ProductId

Một lỗi đã được trả lại và không có gì được chèn vào.

Điều này tương đương với việc sử dụng OR ABORT tùy chọn.

INSERT OR ABORT INTO Products VALUES (1, 'Wrench', 12.50);

Kết quả:

Error: UNIQUE constraint failed: Products.ProductId

Chúng tôi có thể xác minh rằng không có gì được chèn bằng cách chạy SELECT tuyên bố chống lại bảng.

SELECT * FROM Products;

Kết quả:

ProductId   ProductName  Price     
----------  -----------  ----------
1           Hammer       8.0       

Chúng ta có thể thấy rằng bảng chỉ chứa hàng gốc.

Ví dụ 2 - Bỏ qua

Một thay thế là để SQLite bỏ qua hàng vi phạm. Nói cách khác, nó sẽ bỏ qua hàng và tiếp tục xử lý các hàng tiếp theo.

Để thực hiện việc này trong INSERT của bạn tuyên bố, sử dụng OR IGNORE .

Tác dụng của việc này là INSERT thao tác thành công nhưng không có bất kỳ hàng nào vi phạm giới hạn khóa chính.

INSERT OR IGNORE INTO Products VALUES 
  (1, 'Hammer', 12.00),
  (2, 'Nails', 2.50),
  (3, 'Saw', 10.50),
  (1, 'Wrench', 22.50),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products;

Kết quả:

ProductId   ProductName  Price     
----------  -----------  ----------
1           Hammer       8.0       
2           Nails        2.5       
3           Saw          10.5      
5           Chisel       23.0      
6           Bandage      120.0     

Trong trường hợp này, tôi đã cố gắng chèn hai hàng mới với một ID đã tồn tại trong bảng, vì vậy cả hai hàng đó đều bị bỏ qua.

Ví dụ 3 - Thay thế

Một tùy chọn khác mà bạn có là thay thế hàng ban đầu bằng hàng mới.

Nói cách khác, bạn sẽ ghi đè dữ liệu hiện có bằng dữ liệu mới của mình.

Để thực hiện việc này, hãy sử dụng OR REPLACE .

INSERT OR REPLACE INTO Products VALUES 
  (1, 'Hammer', 12.00),
  (2, 'Nails', 2.50),
  (3, 'Saw', 10.50),
  (1, 'Wrench', 22.50),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products;

Kết quả:

ProductId   ProductName  Price     
----------  -----------  ----------
1           Wrench       22.5      
2           Nails        2.5       
3           Saw          10.5      
5           Chisel       23.0      
6           Bandage      120.0     

Trong trường hợp này, hầu hết các hàng đều giống nhau, vì vậy chúng chứa cùng một dữ liệu sau INSERT hoạt động. Tuy nhiên, chúng ta có thể thấy rằng hàng đầu tiên đã được cập nhật để sử dụng các giá trị trong INSERT của tôi tuyên bố.

Chúng tôi cũng có thể thấy rằng nó đã sử dụng bộ giá trị thứ hai (coi như hai giá trị được chia sẻ cùng một ProductId ).

Vì vậy, hiệu ứng giống như một UPDATE câu lệnh và INSERT tuyên bố kết hợp.

Ví dụ 4 - Khôi phục

Một tùy chọn khác là sử dụng ROLLBACK tùy chọn.

Thao tác này hủy bỏ câu lệnh SQL hiện tại với lỗi SQLITE_CONSTRAINT và khôi phục giao dịch hiện tại. Nếu không có giao dịch nào đang hoạt động (ngoài giao dịch ngụ ý được tạo trên mọi lệnh) thì giao dịch đó hoạt động giống như ABORT thuật toán.

Cần lưu ý đến cách thức hoạt động của tùy chọn này. Dưới đây là một ví dụ sử dụng nhiều INSERT OR ROLLBACK báo cáo trong một giao dịch.

DELETE FROM Products;

BEGIN TRANSACTION;
INSERT OR ROLLBACK INTO Products VALUES (1, 'Hammer', 8.00);
INSERT OR ROLLBACK INTO Products VALUES (2, 'Nails', 2.50);
INSERT OR ROLLBACK INTO Products VALUES (3, 'Saw', 10.50);
INSERT OR ROLLBACK INTO Products VALUES (1, 'Wrench', 22.50);
INSERT OR ROLLBACK INTO Products VALUES (5, 'Chisel', 23.00);
INSERT OR ROLLBACK INTO Products VALUES (6, 'Bandage', 120.00);
COMMIT;
  
SELECT * FROM Products;

Đây là kết quả đầu ra đầy đủ từ thiết bị đầu cuối của tôi khi tôi chạy điều này:

sqlite> BEGIN TRANSACTION;
sqlite> INSERT OR ROLLBACK INTO Products VALUES (1, 'Hammer', 8.00);
sqlite> INSERT OR ROLLBACK INTO Products VALUES (2, 'Nails', 2.50);
sqlite> INSERT OR ROLLBACK INTO Products VALUES (3, 'Saw', 10.50);
sqlite> INSERT OR ROLLBACK INTO Products VALUES (1, 'Wrench', 22.50);
Error: UNIQUE constraint failed: Products.ProductId
sqlite> INSERT OR ROLLBACK INTO Products VALUES (5, 'Chisel', 23.00);
sqlite> INSERT OR ROLLBACK INTO Products VALUES (6, 'Bandage', 120.00);
sqlite> COMMIT;
Error: cannot commit - no transaction is active
sqlite>   
sqlite> SELECT * FROM Products;
ProductId   ProductName  Price     
----------  -----------  ----------
5           Chisel       23.0      
6           Bandage      120.0     
sqlite> 

Về cơ bản những gì đã xảy ra ở đây là, nó đã đi đến mức vi phạm ràng buộc, sau đó quay trở lại giao dịch. Sau đó, hai dòng tiếp theo được xử lý và sau đó là COMMIT từ khóa đã gặp phải. Đến lúc đó, giao dịch đã được khôi phục và do đó, chúng tôi gặp một lỗi khác cho chúng tôi biết rằng không có giao dịch nào đang hoạt động.

Đây là những gì sẽ xảy ra nếu tôi xóa nó khỏi giao dịch.

DELETE FROM Products;

INSERT OR ROLLBACK INTO Products VALUES (1, 'Hammer', 8.00);
INSERT OR ROLLBACK INTO Products VALUES (2, 'Nails', 2.50);
INSERT OR ROLLBACK INTO Products VALUES (3, 'Saw', 10.50);
INSERT OR ROLLBACK INTO Products VALUES (1, 'Wrench', 22.50);
INSERT OR ROLLBACK INTO Products VALUES (5, 'Chisel', 23.00);
INSERT OR ROLLBACK INTO Products VALUES (6, 'Bandage', 120.00);
  
SELECT * FROM Products;

Đây là kết quả đầu ra đầy đủ từ thiết bị đầu cuối của tôi khi tôi chạy điều này:

sqlite> DELETE FROM Products;
sqlite> 
sqlite> INSERT OR ROLLBACK INTO Products VALUES (1, 'Hammer', 8.00);
sqlite> INSERT OR ROLLBACK INTO Products VALUES (2, 'Nails', 2.50);
sqlite> INSERT OR ROLLBACK INTO Products VALUES (3, 'Saw', 10.50);
sqlite> INSERT OR ROLLBACK INTO Products VALUES (1, 'Wrench', 22.50);
Error: UNIQUE constraint failed: Products.ProductId
sqlite> INSERT OR ROLLBACK INTO Products VALUES (5, 'Chisel', 23.00);
sqlite> INSERT OR ROLLBACK INTO Products VALUES (6, 'Bandage', 120.00);
sqlite>   
sqlite> SELECT * FROM Products;
ProductId   ProductName  Price     
----------  -----------  ----------
1           Hammer       8.0       
2           Nails        2.5       
3           Saw          10.5      
5           Chisel       23.0      
6           Bandage      120.0     
sqlite>

Trong trường hợp này, nó hoạt động giống như ABORT .

Để chứng minh điều này, đây là câu lệnh tương tự sử dụng ABORT thay vì ROLLBACK .

DELETE FROM Products;

INSERT OR ABORT INTO Products VALUES (1, 'Hammer', 8.00);
INSERT OR ABORT INTO Products VALUES (2, 'Nails', 2.50);
INSERT OR ABORT INTO Products VALUES (3, 'Saw', 10.50);
INSERT OR ABORT INTO Products VALUES (1, 'Wrench', 22.50);
INSERT OR ABORT INTO Products VALUES (5, 'Chisel', 23.00);
INSERT OR ABORT INTO Products VALUES (6, 'Bandage', 120.00);
  
SELECT * FROM Products;

Đây là kết quả đầu ra đầy đủ từ thiết bị đầu cuối của tôi khi tôi chạy điều này:

sqlite> DELETE FROM Products;
sqlite> 
sqlite> INSERT OR ABORT INTO Products VALUES (1, 'Hammer', 8.00);
sqlite> INSERT OR ABORT INTO Products VALUES (2, 'Nails', 2.50);
sqlite> INSERT OR ABORT INTO Products VALUES (3, 'Saw', 10.50);
sqlite> INSERT OR ABORT INTO Products VALUES (1, 'Wrench', 22.50);
Error: UNIQUE constraint failed: Products.ProductId
sqlite> INSERT OR ABORT INTO Products VALUES (5, 'Chisel', 23.00);
sqlite> INSERT OR ABORT INTO Products VALUES (6, 'Bandage', 120.00);
sqlite>   
sqlite> SELECT * FROM Products;
ProductId   ProductName  Price     
----------  -----------  ----------
1           Hammer       8.0       
2           Nails        2.5       
3           Saw          10.5      
5           Chisel       23.0      
6           Bandage      120.0     
sqlite> 

Tùy chọn thất bại

FAIL tùy chọn hủy bỏ câu lệnh SQL hiện tại với lỗi SQLITE_CONSTRAINT. Nhưng tùy chọn này không hỗ trợ các thay đổi trước đó của câu lệnh SQL không thành công cũng như không kết thúc giao dịch.

DELETE FROM Products;

INSERT OR FAIL INTO Products VALUES 
  (1, 'Hammer', 8.00),
  (2, 'Nails', 2.50),
  (3, 'Saw', 10.50),
  (1, 'Wrench', 22.50),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products;

Kết quả:

ProductId   ProductName  Price     
----------  -----------  ----------
1           Hammer       8.0       
2           Nails        2.5       
3           Saw          10.5      

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQLite JSON_REPLACE ()

  2. GreenDAO hỗ trợ nhiều mối quan hệ giữa các bảng

  3. SQLite MAX

  4. Cách cài đặt phiên bản Sqlite aar mới nhất khi sử dụng Room On Android

  5. Cách hoạt động của SQLite Length ()