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

Làm thế nào ON CONFLICT hoạt động trong SQLite

SQLite có ON CONFLICT mệnh đề cho phép bạn chỉ định cách xử lý xung đột ràng buộc. Nó áp dụng cho UNIQUE , NOT NULL , CHECKPRIMARY KEY ràng buộc (nhưng không phải FOREIGN KEY ràng buộc).

Có năm tùy chọn khả thi mà bạn có thể sử dụng với điều khoản này:

  • ABORT
  • FAIL
  • IGNORE
  • REPLACE
  • ROLLBACK

Bài viết này cung cấp các ví dụ và giải thích về từng tùy chọn này.

ON CONFLICT mệnh đề được sử dụng trong CREATE TABLE nhưng nó cũng có thể được sử dụng khi chèn hoặc cập nhật dữ liệu bằng cách thay thế ON CONFLICT với OR .

Khi tạo bảng

Như đã đề cập, bạn có thể sử dụng ON CONFLICT khi bạn tạo bảng hoặc khi bạn chèn / cập nhật dữ liệu.

Đây là một ví dụ về việc sử dụng ON CONFLICT tại thời điểm tạo bảng.

 CREATE TABLE Products( 
    ProductId INTEGER PRIMARY KEY, 
    ProductName NOT NULL ON CONFLICT IGNORE, 
    Price
); 

Khi bạn sử dụng ON CONFLICT , bạn áp dụng nó cho ràng buộc cụ thể mà bạn muốn xử lý. Trong trường hợp này, tôi đã thêm mệnh đề vào NOT NULL ràng buộc.

Trong trường hợp này, tôi đã chỉ định IGNORE , có nghĩa là, nếu có vi phạm ràng buộc, SQLite sẽ bỏ qua hàng đó và sau đó tiếp tục xử lý.

Bây giờ nếu tôi cố gắng chèn NULL vào Tên sản phẩm cột mà hàng bị bỏ qua.

 INSERT INTO Products VALUES 
  (1, 'Hammer', 9.99),
  (2, NULL, 1.49),
  (3, 'Saw', 11.34),
  (4, 'Wrench', 37.00),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products; 

Kết quả:

 ProductId ProductName Giá ------------------------------ 1 Búa 9,99 3 Cưa 11,34 4 Cờ lê 37,0 5 Đục 23,0 6 Băng keo 120.0 

Khi chèn dữ liệu

Bạn cũng có thể sử dụng mệnh đề này khi chèn và cập nhật dữ liệu. Sự khác biệt là bạn thay thế ON CONFLICT với OR .

Để chứng minh, tôi sẽ thả bảng trước đó và tạo lại nó, nhưng không có ON CONFLICT mệnh đề:

 DROP TABLE IF EXISTS Products;

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

Bây giờ tôi sẽ chèn cùng một dữ liệu và sử dụng OR IGNORE để bỏ qua hàng vi phạm ràng buộc.

 INSERT OR IGNORE INTO Products VALUES 
  (1, 'Hammer', 9.99),
  (2, NULL, 1.49),
  (3, 'Saw', 11.34),
  (4, 'Wrench', 37.00),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products; 

Kết quả:

 ProductId ProductName Giá ------------------------------ 1 Búa 9,99 3 Cưa 11,34 4 Cờ lê 37,0 5 Đục 23,0 6 Băng keo 120.0 

Vì vậy, chúng tôi nhận được kết quả tương tự như trong ví dụ trước.

Trong các ví dụ này, tôi đã sử dụng IGNORE lựa chọn. Đây chỉ là một trong năm lựa chọn khả thi cho điều khoản này.

Dưới đây là các ví dụ sử dụng từng tùy chọn trong số năm tùy chọn.

Hủy bỏ

Tùy chọn này hủy bỏ câu lệnh SQL hiện tại với lỗi SQLITE_CONSTRAINT và sao lưu bất kỳ thay đổi nào được thực hiện bởi câu lệnh SQL hiện tại; nhưng những thay đổi do các câu lệnh SQL trước đó gây ra trong cùng một giao dịch được giữ nguyên và giao dịch vẫn hoạt động.

Đây là hành vi mặc định. Nói cách khác, đây là những gì xảy ra khi vi phạm ràng buộc khi bạn không sử dụng ON CONFLICT mệnh đề.

Dưới đây là một ví dụ về những gì sẽ xảy ra khi bạn chỉ định ABORT .

 DELETE FROM Products;

INSERT OR ABORT INTO Products VALUES 
  (1, 'Hammer', 9.99),
  (2, NULL, 1.49),
  (3, 'Saw', 11.34),
  (4, 'Wrench', 37.00),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products; 

Kết quả:

 

Không có kết quả nào được trả về vì INSERT thao tác đã bị hủy bỏ và bảng do đó trống.

Đây là những gì sẽ xảy ra nếu tôi đặt mỗi hàng trong INSERT của riêng nó tuyên bố trong một giao dịch.

 BEGIN TRANSACTION;
INSERT OR ABORT INTO Products VALUES (1, 'Hammer', 9.99);
INSERT OR ABORT INTO Products VALUES (2, NULL, 1.49);
INSERT OR ABORT INTO Products VALUES (3, 'Saw', 11.34);
INSERT OR ABORT INTO Products VALUES (4, 'Wrench', 37.00);
INSERT OR ABORT INTO Products VALUES (5, 'Chisel', 23.00);
INSERT OR ABORT INTO Products VALUES (6, 'Bandage', 120.00);
COMMIT;
  
SELECT * FROM Products; 

Kết quả:

 ProductId ProductName Giá ------------------------------ 1 Búa 9,99 3 Cưa 11,34 4 Cờ lê 37,0 5 Đục 23,0 6 Băng keo 120.0 

Không thành công

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 nó 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.

Đây là một ví dụ.

 DELETE FROM Products;

INSERT OR FAIL INTO Products VALUES 
  (1, 'Hammer', 9.99),
  (2, NULL, 1.49),
  (3, 'Saw', 11.34),
  (4, 'Wrench', 37.00),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products; 

Kết quả:

 ProductId ProductName Giá ------------------------------ 1 Hammer 9,99 

Đây là nó với INSERT riêng biệt báo cáo trong một giao dịch.

 DELETE FROM Products;

BEGIN TRANSACTION;
INSERT OR FAIL INTO Products VALUES (1, 'Hammer', 9.99);
INSERT OR FAIL INTO Products VALUES (2, NULL, 1.49);
INSERT OR FAIL INTO Products VALUES (3, 'Saw', 11.34);
INSERT OR FAIL INTO Products VALUES (4, 'Wrench', 37.00);
INSERT OR FAIL INTO Products VALUES (5, 'Chisel', 23.00);
INSERT OR FAIL INTO Products VALUES (6, 'Bandage', 120.00);
COMMIT;
  
SELECT * FROM Products; 

Kết quả:

 ProductId ProductName Giá ------------------------------ 1 Búa 9,99 3 Cưa 11,34 4 Cờ lê 37,0 5 Đục 23,0 6 Băng keo 120.0 

Bỏ qua

IGNORE tùy chọn bỏ qua một hàng có vi phạm ràng buộc và tiếp tục xử lý các hàng tiếp theo của câu lệnh SQL như thể không có gì sai. Các hàng khác trước và sau hàng có vi phạm ràng buộc được chèn hoặc cập nhật bình thường. Không có lỗi nào được trả về cho tính duy nhất, NOT NULLUNIQUE lỗi ràng buộc khi tùy chọn này được sử dụng. Tuy nhiên, tùy chọn này hoạt động giống như ABORT đối với lỗi ràng buộc khóa ngoại.

Các ví dụ đầu tiên trên trang này sử dụng IGNORE , nhưng nó lại ở đây.

 DELETE FROM Products;

INSERT OR IGNORE INTO Products VALUES 
  (1, 'Hammer', 9.99),
  (2, NULL, 1.49),
  (3, 'Saw', 11.34),
  (4, 'Wrench', 37.00),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products; 

Kết quả:

 ProductId ProductName Giá ------------------------------ 1 Búa 9,99 3 Cưa 11,34 4 Cờ lê 37,0 5 Đục 23,0 6 Băng keo 120.0 

Thay thế

REPLACE tùy chọn hoạt động khác nhau tùy thuộc vào vi phạm:

  • Khi một UNIQUE hoặc PRIMARY KEY vi phạm ràng buộc xảy ra, REPLACE tùy chọn xóa các hàng tồn tại trước đó gây ra vi phạm ràng buộc trước khi chèn hoặc cập nhật hàng hiện tại và lệnh tiếp tục thực thi bình thường.
  • Nếu một NOT NULL vi phạm ràng buộc xảy ra, nó thay thế NULL giá trị với giá trị mặc định cho cột đó hoặc nếu cột không có giá trị mặc định, thì ABORT thuật toán được sử dụng.
  • Nếu một CHECK ràng buộc hoặc vi phạm ràng buộc khóa ngoại xảy ra, sau đó REPLACE hoạt động giống như ABORT .

Ngoài ra, nếu nó xóa các hàng để đáp ứng một hạn chế, hãy xóa trình kích hoạt kích hoạt nếu và chỉ khi trình kích hoạt đệ quy được bật.

Đây là một ví dụ sử dụng REPLACE lựa chọn.

 DELETE FROM Products; 

INSERT OR REPLACE INTO Products VALUES 
  (1, 'Hammer', 9.99),
  (2, 'Nails', 1.49),
  (3, 'Saw', 11.34),
  (1, 'Wrench', 37.00),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products; 

Kết quả:

 ProductId ProductName Giá ------------------------------ 1 Cờ lê 37.0 2 Đinh 1.49 3 Cưa 11.34 5 Đục 23.0 6 Băng keo 120.0 

Trong ví dụ này, xung đột là với khóa chính (tôi đã cố gắng chèn hai hàng có cùng một ProductId ). REPLACE khiến tùy chọn thứ hai thay thế tùy chọn đầu tiên.

Khôi phục

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

Tùy chọn 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.

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', 9.99);
INSERT OR ROLLBACK INTO Products VALUES (2, NULL, 1.49);
INSERT OR ROLLBACK INTO Products VALUES (3, 'Saw', 11.34);
INSERT OR ROLLBACK INTO Products VALUES (4, 'Wrench', 37.00);
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> XÓA KHỎI Sản phẩm; sqlite> sqlite> BẮT ĐẦU GIAO DỊCH; sqlite> CHÈN HOẶC ROLLBACK VÀO GIÁ TRỊ Sản phẩm (1, 'Hammer', 9,99); sqlite> CHÈN HOẶC QUAY LẠI VÀO GIÁ TRỊ Sản phẩm (2, NULL, 1.49); Lỗi:Ràng buộc NOT NULL không thành công:Products.ProductNamesqlite> INSERT OR ROLLBACK INTO Products VALUES (3, 'Saw', 11.34); sqlite> INSERT OR ROLLBACK INTO Products VALUES (4, 'Wrench', 37,00); sqlite> INSERT OR ROLLBACK VÀO GIÁ TRỊ Sản phẩm (5, 'Chisel', 23,00); sqlite> CHÈN HOẶC ROLLBACK VÀO GIÁ TRỊ Sản phẩm (6, 'Bandage', 120,00); sqlite> COMMIT; Lỗi:không thể cam kết - không có giao dịch nào được kích hoạt> sqlite> CHỌN * TỪ Products; ProductId ProductName Price trước> 

Vì vậy, nó đã vi phạm ràng buộc, sau đó quay trở lại giao dịch. Sau đó, các 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', 9.99);
INSERT OR ROLLBACK INTO Products VALUES (2, NULL, 1.49);
INSERT OR ROLLBACK INTO Products VALUES (3, 'Saw', 11.34);
INSERT OR ROLLBACK INTO Products VALUES (4, 'Wrench', 37.00);
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> XÓA KHỎI Sản phẩm; sqlite> sqlite> CHÈN HOẶC QUAY LẠI VÀO GIÁ TRỊ Sản phẩm (1, 'Hammer', 9,99); sqlite> CHÈN HOẶC LĂN LẠI VÀO GIÁ TRỊ Sản phẩm (2, NULL, 1.49); Lỗi:Ràng buộc KHÔNG ĐỦ không thành công:Products.ProductNamesqlite> INSERT HOẶC QUAY LẠI VÀO GIÁ TRỊ Sản phẩm (3, 'Saw', 11,34); sqlite> CHÈN HOẶC ROLLBACK VÀO GIÁ TRỊ Sản phẩm (4, 'Cờ lê', 37,00); sqlite> CHÈN HOẶC ROLLBACK VÀO GIÁ TRỊ Sản phẩm (5 , 'Chisel', 23.00); sqlite> CHÈN HOẶC QUAY LẠI VÀO GIÁ TRỊ Sản phẩm (6, 'Bandage', 120.00); sqlite> sqlite> CHỌN * TỪ Sản phẩm; ProductId ProductName Giá ---------- - --------- ---------- 1 Búa 9,99 3 Cưa 11,34 4 Cờ lê 37,0 5 Đục 23,0 6 Băng 120,0 

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

Để xác nhận, đâ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', 9.99);
INSERT OR ABORT INTO Products VALUES (2, NULL, 1.49);
INSERT OR ABORT INTO Products VALUES (3, 'Saw', 11.34);
INSERT OR ABORT INTO Products VALUES (4, 'Wrench', 37.00);
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> XÓA TỪ SẢN PHẨM; sqlite> sqlite> CHÈN HOẶC NHẬP VÀO GIÁ TRỊ Sản phẩm (1, 'Hammer', 9,99); sqlite> CHÈN HOẶC NHẬP VÀO GIÁ TRỊ Sản phẩm (2, NULL, 1.49); Lỗi:Ràng buộc NOT NULL không thành công:Products.ProductNamesqlite> CHÈN HOẶC NHẬP VÀO GIÁ TRỊ Sản phẩm (3, 'Saw', 11,34); sqlite> CHÈN HOẶC NHẬP VÀO GIÁ TRỊ Sản phẩm (4, 'Cờ lê', 37,00); sqlite> CHÈN HOẶC NHẬP VÀO GIÁ TRỊ Sản phẩm (5 , 'Chisel', 23,00); sqlite> CHÈN HOẶC NHẬP VÀO GIÁ TRỊ Sản phẩm (6, 'Bandage', 120,00); sqlite> sqlite> CHỌN * TỪ Sản phẩm; ProductId ProductName Giá ---------- - --------- ---------- 1 Búa 9,99 3 Cưa 11,34 4 Cờ lê 37,0 5 Đục 23,0 6 Băng 120,0 


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Android SQLite:Làm thế nào để tạo bảng lớn cho mục đích thử nghiệm?

  2. Trả lại mảng chuỗi và sử dụng nó trên AutoCompleteTextview

  3. Chèn SQLite

  4. SQLite - Cập nhật dữ liệu

  5. Bảng cơ sở dữ liệu Android SQLite không được tạo