Một trong những phần mở rộng không chuẩn của SQLite đối với SQL là ON CONFLICT
mệnh đề.
Điều khoản này cho phép bạn xác định điều gì sẽ xảy ra khi một số xung đột nhất định xảy ra do vi phạm ràng buộc.
Một trong những điều bạn có thể sử dụng mệnh đề này là thay thế NULL
giá trị với giá trị mặc định của cột khi chèn hoặc cập nhật dữ liệu trong bảng.
Theo mặc định, nếu bạn cố gắng chèn NULL
một cách rõ ràng vào một cột có NOT NULL
ràng buộc, nó sẽ thất bại.
Và nếu bạn cố gắng chèn NULL
một cách rõ ràng vào một cột không có a NOT NULL
ràng buộc, rồi đến NULL
sẽ được chỉ định cho cột đó, ngay cả khi có DEFAULT
mệnh đề.
Tuy nhiên, bạn có thể sử dụng ON CONFLICT
để đặt nó thành giá trị mặc định thay vì NULL
.
Ví dụ
Đoạn mã sau giải thích ý tôi muốn nói.
DROP TABLE IF EXISTS Products;
CREATE TABLE Products(
ProductId INTEGER PRIMARY KEY,
ProductName NOT NULL,
Price NOT NULL ON CONFLICT REPLACE DEFAULT 0.00
);
INSERT INTO Products (ProductId, ProductName, Price) VALUES
(1, 'Widget Holder', NULL);
SELECT * FROM Products;
Trong ví dụ này, tôi sử dụng ON CONFLICT REPLACE
để đặt NULL
giá trị thành giá trị mặc định thay vì NULL
.
Đây là kết quả từ SELECT
tuyên bố ở dòng cuối cùng:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Chúng ta có thể thấy rằng Giá cột có giá trị mặc định là 0.0 mặc dù tôi đã cố chèn NULL
một cách rõ ràng .
Hãy xem điều gì sẽ xảy ra nếu tôi xóa NOT NULL
ràng buộc.
DROP TABLE IF EXISTS Products;
CREATE TABLE Products(
ProductId INTEGER PRIMARY KEY,
ProductName NOT NULL,
Price DEFAULT 0.00
);
INSERT INTO Products (ProductId, ProductName, Price) VALUES
(1, 'Widget Holder', NULL);
SELECT * FROM Products;
Kết quả:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder
Bây giờ cột chứa NULL
.
Chèn NULL một cách ngầm định
Điều quan trọng cần lưu ý là bài viết này chủ yếu liên quan đến việc chèn NULL
rõ ràng .
Nếu bạn cố gắng chèn NULL
ngầm định , thì ví dụ trước sẽ tạo ra một kết quả khác.
Ý tôi là, nếu bạn không đưa cột vào INSERT
câu lệnh, DEFAULT
ràng buộc sẽ được sử dụng tự động. Đó là những gì DEFAULT
ràng buộc là để - cung cấp một giá trị khi bạn không cung cấp một cách rõ ràng.
Đây là những gì sẽ xảy ra khi tôi làm điều đó.
DROP TABLE IF EXISTS Products;
CREATE TABLE Products(
ProductId INTEGER PRIMARY KEY,
ProductName NOT NULL,
Price DEFAULT 0.00
);
INSERT INTO Products (ProductId, ProductName) VALUES
(1, 'Widget Holder');
SELECT * FROM Products;
Kết quả:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Vì vậy, tất cả những gì tôi đã làm là xóa Giá từ cột INSERT
tuyên bố.
BẤT NGỜ đối với Tuyên bố INSERT
Ví dụ đầu tiên sử dụng ON CONFLICT
trên CREATE TABLE
tuyên bố.
Nhưng điều gì sẽ xảy ra nếu bảng không được tạo bằng ON CONFLICT
mệnh đề?
May mắn thay, cũng có một cách để sử dụng nó trên INSERT
tuyên bố.
Cú pháp hơi khác một chút. Khi được sử dụng trên INSERT
câu lệnh bạn cần thay thế ON CONFLICT
với OR
.
Hãy sửa đổi mã để sử dụng phương pháp này.
DROP TABLE IF EXISTS Products;
CREATE TABLE Products(
ProductId INTEGER PRIMARY KEY,
ProductName NOT NULL,
Price NOT NULL DEFAULT 0.00
);
INSERT OR REPLACE INTO Products (ProductId, ProductName, Price) VALUES
(1, 'Widget Holder', NULL);
SELECT * FROM Products;
Kết quả:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Vì vậy, tôi đã thay thế INSERT INTO
với INSERT OR REPLACE INTO
.
Đây là kết quả nếu tôi không đưa điều khoản đó vào.
DROP TABLE IF EXISTS Products;
CREATE TABLE Products(
ProductId INTEGER PRIMARY KEY,
ProductName NOT NULL,
Price NOT NULL DEFAULT 0.00
);
INSERT INTO Products (ProductId, ProductName, Price) VALUES
(1, 'Widget Holder', NULL);
SELECT * FROM Products;
Kết quả:
Error: NOT NULL constraint failed: Products.Price
Không có Ràng buộc DEFAULT?
Trong trường hợp bạn sử dụng ON CONFLICT
mệnh đề trên cột không có DEFAULT
ràng buộc, câu lệnh SQL bị hủy bỏ với lỗi SQLITE_CONSTRAINT bất kỳ thay đổi nào được thực hiện bởi câu lệnh SQL hiện tại đều được sao lưu; 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.