SQLiteのSQLに対する非標準の拡張機能の1つは、ON CONFLICT
です。 条項。
この句を使用すると、制約違反が原因で特定の競合が発生した場合に何が発生するかを判断できます。
この句を使用できることの1つは、NULL
を置き換えることです。 テーブルにデータを挿入または更新するときの列のデフォルト値を持つ値。
デフォルトでは、NULL
を明示的に挿入しようとすると NOT NULL
の列に 制約、それは失敗します。
また、NULL
を明示的に挿入しようとすると なしの列に NOT NULL
制約、次にNULL
DEFAULT
がある場合でも、その列に割り当てられます 条項。
ただし、ON CONFLICT
は使用できます NULL
ではなくデフォルト値に設定する句 。
例
次のコードは、私が何を意味するかを示しています。
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;
この例では、ON CONFLICT REPLACE
を使用します NULL
を設定するには 値をNULL
ではなくデフォルト値に変更 。
これがSELECT
の結果です 最後の行のステートメント:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
価格がわかります NULL
を明示的に挿入しようとしましたが、columnのデフォルト値は0.0です。 。
NOT NULL
を削除するとどうなるか見てみましょう 制約。
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;
結果:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder
これで、列にNULL
が含まれます 。
暗黙的にNULLを挿入する
この記事は主にNULL
の挿入に関係していることに注意してください。 明示的に 。
NULL
を挿入しようとした場合 暗黙的に 、その場合、前の例では異なる結果が生成されます。
つまり、INSERT
に列を含めない場合です。 ステートメント、DEFAULT
制約は自動的に使用されます。それがDEFAULT
制約は–明示的に値を提供しない場合に値を提供するためのものです。
これを行うとどうなりますか。
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;
結果:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
だから私がしたのは価格を削除することだけでした INSERT
の列 ステートメント。
INSERTステートメントの競合について
最初の例では、ON CONFLICT
を使用しています CREATE TABLE
で ステートメント。
ただし、テーブルがON CONFLICT
で作成されていない場合はどうなりますか 条項?
幸い、INSERT
で使用する方法もあります 声明。
構文は少し異なります。 INSERT
で使用する場合 ON CONFLICT
を置き換える必要があるステートメント OR
を使用 。
このメソッドを使用するようにコードを変更しましょう。
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;
結果:
ProductId ProductName Price ---------- ------------- ---------- 1 Widget Holder 0.0
そこで、INSERT INTO
を置き換えました INSERT OR REPLACE INTO
を使用 。
その条項を入れなかった場合の結果は次のとおりです。
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;
結果:
Error: NOT NULL constraint failed: Products.Price
デフォルトの制約はありませんか?
ON CONFLICT
を使用する場合 DEFAULT
のない列の句 制約がある場合、SQLステートメントはSQLITE_CONSTRAINTエラーで中止され、現在のSQLステートメントによって行われた変更はすべて取り消されます。ただし、同じトランザクション内の以前のSQLステートメントによって引き起こされた変更は保持され、トランザクションはアクティブなままです。