Uma das extensões não padrão do SQLite para SQL é o
ON CONFLICT cláusula. Esta cláusula permite determinar o que deve acontecer quando determinados conflitos ocorrerem devido a uma violação de restrição.
Uma das coisas para as quais você pode usar esta cláusula é substituir
NULL valores com o valor padrão de uma coluna ao inserir ou atualizar dados em uma tabela. Por padrão, se você tentar inserir explicitamente
NULL em uma coluna com um NOT NULL restrição, ele falhará. E se você tentar inserir explicitamente
NULL em uma coluna sem a NOT NULL restrição, então NULL será atribuído a essa coluna, mesmo se houver um DEFAULT cláusula. No entanto, você pode usar o
ON CONFLICT cláusula para defini-lo com o valor padrão em vez de NULL . Exemplo
O código a seguir demonstra o que quero dizer.
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; Neste exemplo eu uso
ON CONFLICT REPLACE para definir NULL valores para o valor padrão em vez de NULL . Aqui está o resultado do
SELECT declaração na última linha:ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Podemos ver que o Preço coluna tem o valor padrão de 0.0, embora eu tenha tentado inserir explicitamente
NULL . Vamos ver o que acontece se eu remover o
NOT NULL limitação. 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; Resultado:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder
Agora a coluna contém
NULL . Inserindo NULL implicitamente
É importante observar que este artigo se preocupa principalmente com a inserção de
NULL explicitamente . Se você tentar inserir
NULL implicitamente , o exemplo anterior produzirá um resultado diferente. O que quero dizer é que, se você não incluir a coluna no
INSERT instrução, o DEFAULT restrição será usada automaticamente. É isso que DEFAULT restrições são para – para fornecer um valor quando você não fornece um explicitamente. Aqui está o que acontece quando eu faço isso.
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; Resultado:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Então, tudo o que fiz foi remover o Preço coluna do
INSERT demonstração. ON CONFLICT para a declaração INSERT
O primeiro exemplo usa
ON CONFLICT no CREATE TABLE demonstração. Mas e se a tabela não foi criada com o
ON CONFLICT cláusula? Felizmente, também há uma maneira de usá-lo no
INSERT demonstração. A sintaxe é um pouco diferente. Quando usado no
INSERT declaração você precisa substituir ON CONFLICT com OR . Vamos modificar o código para usar este método.
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; Resultado:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Então eu substituí
INSERT INTO com INSERT OR REPLACE INTO . Aqui está o que o resultado seria se eu não tivesse colocado essa cláusula.
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; Resultado:
Error: NOT NULL constraint failed: Products.Price
Nenhuma restrição DEFAULT?
No caso de você usar o
ON CONFLICT cláusula em uma coluna sem um DEFAULT restrição, a instrução SQL é abortada com um erro SQLITE_CONSTRAINT todas as alterações feitas pela instrução SQL atual são desfeitas; mas as alterações causadas por instruções SQL anteriores na mesma transação são preservadas e a transação permanece ativa.