En av SQLites icke-standardiserade tillägg till SQL är ON CONFLICT
klausul.
Denna klausul låter dig bestämma vad som ska hända när vissa konflikter uppstår på grund av en överträdelse av begränsningar.
En av sakerna du kan använda den här klausulen till är att ersätta NULL
värden med en kolumns standardvärde när du infogar eller uppdaterar data i en tabell.
Som standard, om du försöker att uttryckligen infoga NULL
i en kolumn med NOT NULL
begränsning, kommer det att misslyckas.
Och om du försöker att uttryckligen infoga NULL
i en kolumn utan en NOT NULL
begränsning, sedan NULL
kommer att tilldelas den kolumnen, även om det finns en DEFAULT
klausul.
Du kan dock använda ON CONFLICT
sats för att ställa in det till standardvärdet istället för NULL
.
Exempel
Följande kod visar vad jag menar.
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;
I det här exemplet använder jag ON CONFLICT REPLACE
för att ställa in NULL
värden till standardvärdet istället för NULL
.
Här är resultatet från SELECT
uttalande på sista raden:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Vi kan se att Pris kolumn har standardvärdet 0.0 även om jag försökte infoga NULL
uttryckligen .
Låt oss se vad som händer om jag tar bort NOT NULL
begränsning.
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;
Resultat:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder
Nu innehåller kolumnen NULL
.
Infoga NULL implicit
Det är viktigt att notera att den här artikeln huvudsakligen handlar om att infoga NULL
explicit .
Om du försöker infoga NULL
implicit , då kommer föregående exempel att ge ett annat resultat.
Vad jag menar är om du inte inkluderar kolumnen i INSERT
satsen, DEFAULT
begränsning kommer att användas automatiskt. Det är vad DEFAULT
begränsningar är för – för att tillhandahålla ett värde när du inte uttryckligen tillhandahåller ett.
Det här är vad som händer när jag gör det.
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;
Resultat:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Så allt jag gjorde var att ta bort Priset kolumnen från INSERT
uttalande.
ON CONFLICT för INSERT Statement
Det första exemplet använder ON CONFLICT
på CREATE TABLE
uttalande.
Men tänk om tabellen inte skapades med ON CONFLICT
klausul?
Lyckligtvis finns det också ett sätt att använda det på INSERT
påstående.
Syntaxen är något annorlunda. När den används på INSERT
uttalande du behöver för att ersätta ON CONFLICT
med OR
.
Låt oss ändra koden för att använda den här metoden.
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;
Resultat:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Så jag ersatte INSERT INTO
med INSERT OR REPLACE INTO
.
Här är vad resultatet skulle bli om jag inte hade lagt in den klausulen.
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;
Resultat:
Error: NOT NULL constraint failed: Products.Price
Ingen DEFAULT-begränsning?
I händelse av att du använder ON CONFLICT
sats på en kolumn utan DEFAULT
begränsning, SQL-satsen avbryts med ett SQLITE_CONSTRAINT-fel alla ändringar som gjorts av den aktuella SQL-satsen backas ut; men ändringar orsakade av tidigare SQL-satser inom samma transaktion bevaras och transaktionen förblir aktiv.