Una delle estensioni non standard di SQLite a SQL è ON CONFLICT
clausola.
Questa clausola consente di determinare cosa dovrebbe accadere quando si verificano determinati conflitti a causa di una violazione di un vincolo.
Una delle cose per cui puoi usare questa clausola è sostituire NULL
valori con il valore predefinito di una colonna durante l'inserimento o l'aggiornamento di dati in una tabella.
Per impostazione predefinita, se provi a inserire esplicitamente NULL
in una colonna con un NOT NULL
vincolo, fallirà.
E se provi a inserire esplicitamente NULL
in una colonna senza a NOT NULL
vincolo, quindi NULL
verrà assegnato a quella colonna, anche se è presente un DEFAULT
clausola.
Tuttavia, puoi utilizzare il ON CONFLICT
clausola per impostarlo sul valore predefinito invece di NULL
.
Esempio
Il codice seguente mostra cosa intendo.
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;
In questo esempio utilizzo ON CONFLICT REPLACE
per impostare NULL
valori al valore predefinito invece di NULL
.
Ecco il risultato di SELECT
dichiarazione sull'ultima riga:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Possiamo vedere che il Prezzo la colonna ha il valore predefinito di 0.0 anche se ho provato a inserire esplicitamente NULL
.
Vediamo cosa succede se rimuovo il NOT NULL
vincolo.
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;
Risultato:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder
Ora la colonna contiene NULL
.
Inserimento implicito di NULL
È importante notare che questo articolo riguarda principalmente l'inserimento di NULL
esplicitamente .
Se provi a inserire NULL
implicitamente , l'esempio precedente produrrà un risultato diverso.
Voglio dire, se non includi la colonna in INSERT
istruzione, il DEFAULT
il vincolo verrà utilizzato automaticamente. Ecco cosa DEFAULT
i vincoli servono a:fornire un valore quando non ne fornisci uno esplicitamente.
Ecco cosa succede quando lo faccio.
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;
Risultato:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Quindi tutto ciò che ho fatto è stato rimuovere il Prezzo colonna da INSERT
dichiarazione.
SUL CONFLITTO per la dichiarazione INSERT
Il primo esempio usa ON CONFLICT
nel CREATE TABLE
dichiarazione.
Ma cosa succede se la tabella non è stata creata con ON CONFLICT
clausola?
Fortunatamente, c'è anche un modo per usarlo su INSERT
dichiarazione.
La sintassi è leggermente diversa. Se utilizzato su INSERT
dichiarazione devi sostituire ON CONFLICT
con OR
.
Modifichiamo il codice per utilizzare questo metodo.
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;
Risultato:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Quindi ho sostituito INSERT INTO
con INSERT OR REPLACE INTO
.
Ecco quale sarebbe il risultato se non avessi inserito quella clausola.
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;
Risultato:
Error: NOT NULL constraint failed: Products.Price
Nessun vincolo PREDEFINITO?
Nel caso in cui utilizzi il ON CONFLICT
clausola su una colonna senza un DEFAULT
vincolo, l'istruzione SQL viene interrotta con un errore SQLITE_CONSTRAINT tutte le modifiche apportate dall'istruzione SQL corrente vengono annullate; ma le modifiche causate da precedenti istruzioni SQL all'interno della stessa transazione vengono conservate e la transazione rimane attiva.