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.