Едно от нестандартните разширения на SQLite към SQL е ON CONFLICT клауза.
Тази клауза ви позволява да определите какво трябва да се случи, когато възникнат определени конфликти поради нарушение на ограничението.
Едно от нещата, за които можете да използвате тази клауза, е да замените NULL стойности със стойността по подразбиране на колона при вмъкване или актуализиране на данни в таблица.
По подразбиране, ако се опитате изрично да вмъкнете NULL в колона с NOT NULL ограничение, то ще се провали.
И ако се опитате изрично да вмъкнете NULL в колона без a NOT NULL ограничение, след това NULL ще бъде присвоен на тази колона, дори ако има DEFAULT клауза.
Можете обаче да използвате ON CONFLICT клауза, за да го зададете на стойността по подразбиране вместо NULL .
Пример
Следният код показва какво имам предвид.
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;
В този пример използвам ON CONFLICT REPLACE за да зададете NULL стойности към стойността по подразбиране вместо NULL .
Ето резултата от SELECT изявление на последния ред:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Виждаме, че Цената колоната има стойност по подразбиране 0.0, въпреки че се опитах изрично да вмъкна NULL .
Нека видим какво ще се случи, ако премахна NOT NULL ограничение.
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; Резултат:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder
Сега колоната съдържа NULL .
Неявно вмъкване на NULL
Важно е да се отбележи, че тази статия се занимава основно с вмъкване на NULL изрично .
Ако се опитате да вмъкнете NULL имплицитно , тогава предишният пример ще даде различен резултат.
Имам предвид, че ако не включите колоната в INSERT оператор, DEFAULT ограничението ще се използва автоматично. Това е, което DEFAULT ограниченията са за – за предоставяне на стойност, когато не сте предоставили изрично такава.
Ето какво се случва, когато го направя.
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; Резултат:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Така че всичко, което направих, беше да премахна Цена колона от INSERT изявление.
В КОНФЛИКТ за изявлението INSERT
Първият пример използва ON CONFLICT на CREATE TABLE изявление.
Но какво ще стане, ако таблицата не е създадена с ON CONFLICT клауза?
За щастие има и начин да го използвате в INSERT изявление.
Синтаксисът е малко по-различен. Когато се използва в INSERT изявление, което трябва да замените ON CONFLICT с OR .
Нека модифицираме кода, за да използваме този метод.
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; Резултат:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Затова замених INSERT INTO с INSERT OR REPLACE INTO .
Ето какъв би бил резултатът, ако не поставих тази клауза.
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; Резултат:
Error: NOT NULL constraint failed: Products.Price
Няма ограничение ПО ПОДРАЗБИРАНЕ?
В случай, че използвате ON CONFLICT клауза в колона без DEFAULT ограничение, SQL операторът се прекратява с грешка SQLITE_CONSTRAINT, всички промени, направени от текущия SQL оператор, се отменят; но промените, причинени от предишни SQL оператори в рамките на същата транзакция, се запазват и транзакцията остава активна.