Una de las extensiones no estándar de SQLite para SQL es ON CONFLICT
cláusula.
Esta cláusula le permite determinar qué debe suceder cuando ocurren ciertos conflictos debido a una violación de restricción.
Una de las cosas para las que puede usar esta cláusula es para reemplazar NULL
valores con el valor predeterminado de una columna al insertar o actualizar datos en una tabla.
De forma predeterminada, si intenta insertar explícitamente NULL
en una columna con NOT NULL
restricción, fallará.
Y si intenta insertar explícitamente NULL
en una columna sin un NOT NULL
restricción, entonces NULL
se asignará a esa columna, incluso si hay un DEFAULT
cláusula.
Sin embargo, puede usar el ON CONFLICT
cláusula para establecerlo en el valor predeterminado en lugar de NULL
.
Ejemplo
El siguiente código demuestra lo que quiero decir.
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;
En este ejemplo uso ON CONFLICT REPLACE
para establecer NULL
valores al valor predeterminado en lugar de NULL
.
Aquí está el resultado de SELECT
declaración en la última línea:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
Podemos ver que el Precio la columna tiene el valor predeterminado de 0.0 aunque intenté insertar explícitamente NULL
.
Veamos qué sucede si elimino el NOT NULL
restricción.
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
Ahora la columna contiene NULL
.
Insertar NULL implícitamente
Es importante tener en cuenta que este artículo trata principalmente de insertar NULL
explícitamente .
Si intenta insertar NULL
implícitamente , entonces el ejemplo anterior producirá un resultado diferente.
Lo que quiero decir es que si no incluye la columna en INSERT
sentencia, el DEFAULT
La restricción se utilizará automáticamente. Eso es lo que DEFAULT
las restricciones son para proporcionar un valor cuando no proporciona uno explícitamente.
Esto es lo que sucede cuando hago eso.
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
Así que todo lo que hice fue eliminar el Precio columna de INSERT
declaración.
ON CONFLICT para la instrucción INSERT
El primer ejemplo usa ON CONFLICT
en CREATE TABLE
declaración.
Pero, ¿y si la tabla no se creó con ON CONFLICT
? cláusula?
Afortunadamente, también hay una forma de usarlo en INSERT
declaración.
La sintaxis es ligeramente diferente. Cuando se usa en INSERT
declaración que necesita reemplazar ON CONFLICT
con OR
.
Modifiquemos el 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
Así que reemplacé INSERT INTO
con INSERT OR REPLACE INTO
.
Este es el resultado si no hubiera incluido esa 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
¿Sin restricción DEFAULT?
En el caso de que uses el ON CONFLICT
cláusula en una columna sin DEFAULT
restricción, la declaración de SQL se aborta con un error SQLITE_CONSTRAINT; todos los cambios realizados por la declaración de SQL actual se revierten; pero los cambios causados por declaraciones SQL anteriores dentro de la misma transacción se conservan y la transacción permanece activa.