Jedním z nestandardních rozšíření SQLite pro SQL je ON CONFLICT
doložka.
Tato klauzule vám umožňuje určit, co by se mělo stát, když dojde k určitým konfliktům kvůli porušení omezení.
Jedna z věcí, pro kterou můžete tuto klauzuli použít, je nahradit NULL
hodnoty s výchozí hodnotou sloupce při vkládání nebo aktualizaci dat v tabulce.
Ve výchozím nastavení, pokud se pokusíte explicitně vložit NULL
do sloupce s NOT NULL
omezení, selže.
A pokud se pokusíte explicitně vložit NULL
do sloupce bez a NOT NULL
omezení a poté NULL
budou přiřazeny tomuto sloupci, i když existuje DEFAULT
doložka.
Můžete však použít ON CONFLICT
klauzule k nastavení na výchozí hodnotu namísto NULL
.
Příklad
Následující kód ukazuje, co tím myslím.
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;
V tomto příkladu používám ON CONFLICT REPLACE
nastavte NULL
hodnoty na výchozí hodnotu namísto NULL
.
Zde je výsledek z SELECT
výpis na posledním řádku:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Vidíme, že Cena sloupec má výchozí hodnotu 0,0, i když jsem se pokusil explicitně vložit NULL
.
Uvidíme, co se stane, když odstraním NOT NULL
omezení.
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;
Výsledek:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder
Nyní sloupec obsahuje NULL
.
Implicitní vložení NULL
Je důležité si uvědomit, že tento článek se zabývá hlavně vkládáním NULL
explicitně .
Pokud se pokusíte vložit NULL
implicitně , pak předchozí příklad poskytne jiný výsledek.
Myslím tím, že pokud sloupec nezahrnete do INSERT
DEFAULT
omezení bude použito automaticky. To je to, co DEFAULT
omezení jsou pro – poskytují hodnotu, když ji výslovně neuvedete.
Zde je to, co se stane, když to udělám.
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;
Výsledek:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Takže vše, co jsem udělal, bylo odstranění Ceny ze sloupce INSERT
prohlášení.
ON CONFLICT pro příkaz INSERT
První příklad používá ON CONFLICT
na CREATE TABLE
prohlášení.
Ale co když tabulka nebyla vytvořena pomocí ON CONFLICT
klauzule?
Naštěstí existuje také způsob, jak jej použít na INSERT
prohlášení.
Syntaxe je mírně odlišná. Při použití na INSERT
příkaz, který musíte nahradit ON CONFLICT
pomocí OR
.
Upravme kód tak, aby používal tuto metodu.
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;
Výsledek:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Tak jsem nahradil INSERT INTO
pomocí INSERT OR REPLACE INTO
.
Zde je výsledek, kdybych tuto klauzuli nevložil.
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;
Výsledek:
Error: NOT NULL constraint failed: Products.Price
Žádné VÝCHOZÍ omezení?
V případě, že použijete ON CONFLICT
klauzule na sloupci bez DEFAULT
omezení, příkaz SQL je přerušen s chybou SQLITE_CONSTRAINT, veškeré změny provedené aktuálním příkazem SQL jsou odvolány; ale změny způsobené předchozími příkazy SQL v rámci stejné transakce jsou zachovány a transakce zůstává aktivní.