sql >> Databáze >  >> RDS >> SQLite

Jak ON CONFLICT funguje v SQLite

SQLite má ON CONFLICT klauzule, která vám umožňuje určit, jak zacházet s konflikty omezení. Platí pro UNIQUE , NOT NULL , CHECK a PRIMARY KEY omezení (ale ne FOREIGN KEY omezení).

S touto klauzulí můžete použít pět možností:

  • ABORT
  • FAIL
  • IGNORE
  • REPLACE
  • ROLLBACK

Tento článek obsahuje příklady a vysvětlení každé z těchto možností.

The ON CONFLICT klauzule se používá v CREATE TABLE příkazy, ale lze jej také použít při vkládání nebo aktualizaci dat nahrazením ON CONFLICT pomocí OR .

Při vytváření tabulky

Jak již bylo zmíněno, můžete použít ON CONFLICT při vytváření tabulky nebo při vkládání/aktualizaci dat.

Zde je příklad použití ON CONFLICT v době vytváření tabulky.

CREATE TABLE Products( 
    ProductId INTEGER PRIMARY KEY, 
    ProductName NOT NULL ON CONFLICT IGNORE, 
    Price
); 

Když použijete ON CONFLICT klauzuli, použijete ji na konkrétní omezení, které chcete zpracovat. V tomto případě jsem klauzuli přidal do NOT NULL omezení.

V tomto případě jsem zadal IGNORE , což znamená, že pokud dojde k porušení omezení, SQLite tento řádek přeskočí a bude pokračovat ve zpracování.

Nyní, když se pokusím vložit NULL do Název produktu sloupec, který je tento řádek přeskočen.

INSERT INTO Products VALUES 
  (1, 'Hammer', 9.99),
  (2, NULL, 1.49),
  (3, 'Saw', 11.34),
  (4, 'Wrench', 37.00),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products; 

Výsledek:

ProductId Název produktu Cena ---------- ----------- ----------1 Kladivo 9,99 3 Pila 11,34 4 Klíč 37,0 5 Sekáč 23,0 6 Obvaz 120,0 

Při vkládání dat

Tuto klauzuli můžete také použít při vkládání a aktualizaci dat. Rozdíl je v tom, že nahradíte ON CONFLICT pomocí OR .

Abych to demonstroval, zruším předchozí tabulku a vytvořím ji znovu, ale bez ON CONFLICT klauzule:

DROP TABLE IF EXISTS Products;

CREATE TABLE Products( 
    ProductId INTEGER PRIMARY KEY, 
    ProductName NOT NULL, 
    Price
); 

Nyní vložím stejná data a použiji OR IGNORE přeskočit řádek, který porušuje omezení.

INSERT OR IGNORE INTO Products VALUES 
  (1, 'Hammer', 9.99),
  (2, NULL, 1.49),
  (3, 'Saw', 11.34),
  (4, 'Wrench', 37.00),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products; 

Výsledek:

ProductId Název produktu Cena ---------- ----------- ----------1 Kladivo 9,99 3 Pila 11,34 4 Klíč 37,0 5 Sekáč 23,0 6 Obvaz 120,0 

Dostaneme tedy stejný výsledek jako v předchozím příkladu.

V těchto příkladech jsem použil IGNORE volba. Toto je pouze jedna z pěti možných možností pro tuto klauzuli.

Níže jsou uvedeny příklady použití každé z pěti možností.

Přerušit

Tato volba zruší aktuální příkaz SQL s chybou SQLITE_CONSTRAINT a zruší všechny změny provedené aktuálním příkazem SQL; ale změny způsobené předchozími příkazy SQL v rámci stejné transakce jsou zachovány a transakce zůstává aktivní.

Toto je výchozí chování. Jinými slovy, toto se stane během porušení omezení, když nepoužijete ON CONFLICT doložka.

Zde je příklad toho, co se stane, když zadáte ABORT .

DELETE FROM Products;

INSERT OR ABORT INTO Products VALUES 
  (1, 'Hammer', 9.99),
  (2, NULL, 1.49),
  (3, 'Saw', 11.34),
  (4, 'Wrench', 37.00),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products; 

Výsledek:

 

Nebyly vráceny žádné výsledky, protože INSERT operace byla přerušena a tabulka je proto prázdná.

Zde je to, co se stane, když vložím každý řádek do vlastního INSERT výpis v rámci transakce.

BEGIN TRANSACTION;
INSERT OR ABORT INTO Products VALUES (1, 'Hammer', 9.99);
INSERT OR ABORT INTO Products VALUES (2, NULL, 1.49);
INSERT OR ABORT INTO Products VALUES (3, 'Saw', 11.34);
INSERT OR ABORT INTO Products VALUES (4, 'Wrench', 37.00);
INSERT OR ABORT INTO Products VALUES (5, 'Chisel', 23.00);
INSERT OR ABORT INTO Products VALUES (6, 'Bandage', 120.00);
COMMIT;
  
SELECT * FROM Products; 

Výsledek:

ProductId Název produktu Cena ---------- ----------- ----------1 Kladivo 9,99 3 Pila 11,34 4 Klíč 37,0 5 Sekáč 23,0 6 Obvaz 120,0 

Neúspěšné

FAIL volba zruší aktuální příkaz SQL s chybou SQLITE_CONSTRAINT. Neodstraní však předchozí změny příkazu SQL, které selhaly, ani neukončí transakci.

Zde je příklad.

DELETE FROM Products;

INSERT OR FAIL INTO Products VALUES 
  (1, 'Hammer', 9.99),
  (2, NULL, 1.49),
  (3, 'Saw', 11.34),
  (4, 'Wrench', 37.00),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products; 

Výsledek:

ProductId ProductName Cena ---------- ----------- ----------1 Hammer 9,99 

Zde je to se samostatným INSERT výpisy v rámci transakce.

DELETE FROM Products;

BEGIN TRANSACTION;
INSERT OR FAIL INTO Products VALUES (1, 'Hammer', 9.99);
INSERT OR FAIL INTO Products VALUES (2, NULL, 1.49);
INSERT OR FAIL INTO Products VALUES (3, 'Saw', 11.34);
INSERT OR FAIL INTO Products VALUES (4, 'Wrench', 37.00);
INSERT OR FAIL INTO Products VALUES (5, 'Chisel', 23.00);
INSERT OR FAIL INTO Products VALUES (6, 'Bandage', 120.00);
COMMIT;
  
SELECT * FROM Products; 

Výsledek:

ProductId Název produktu Cena ---------- ----------- ----------1 Kladivo 9,99 3 Pila 11,34 4 Klíč 37,0 5 Sekáč 23,0 6 Obvaz 120,0 

Ignorovat

IGNORE volba přeskočí jeden řádek, který obsahuje porušení omezení, a pokračuje ve zpracování následujících řádků příkazu SQL, jako by se nic nestalo. Ostatní řádky před a za řádkem, který obsahoval porušení omezení, jsou vloženy nebo aktualizovány normálně. Pro jedinečnost není vrácena žádná chyba, NOT NULL a UNIQUE chyby omezení při použití této možnosti. Tato možnost však funguje jako ABORT pro chyby omezení cizího klíče.

První příklady na této stránce používají IGNORE , ale je to tu znovu.

DELETE FROM Products;

INSERT OR IGNORE INTO Products VALUES 
  (1, 'Hammer', 9.99),
  (2, NULL, 1.49),
  (3, 'Saw', 11.34),
  (4, 'Wrench', 37.00),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products; 

Výsledek:

ProductId Název produktu Cena ---------- ----------- ----------1 Kladivo 9,99 3 Pila 11,34 4 Klíč 37,0 5 Sekáč 23,0 6 Obvaz 120,0 

Nahradit

REPLACE Tato možnost funguje odlišně v závislosti na porušení:

  • Pokud je UNIQUE nebo PRIMARY KEY dojde k porušení omezení, REPLACE Před vložením nebo aktualizací aktuálního řádku odstraní již existující řádky, které způsobují porušení omezení, a příkaz pokračuje v normálním provádění.
  • Pokud NOT NULL dojde k porušení omezení, nahradí NULL hodnotu s výchozí hodnotou pro daný sloupec, nebo pokud sloupec nemá žádnou výchozí hodnotu, pak ABORT je použit algoritmus.
  • Pokud CHECK dojde k porušení omezení nebo omezení cizího klíče, poté REPLACE funguje jako ABORT .

Pokud také odstraní řádky za účelem splnění omezení, spouštěcí spouštěče se spouštějí pouze tehdy, jsou-li povoleny rekurzivní spouštěče.

Zde je příklad, který používá REPLACE volba.

DELETE FROM Products; 

INSERT OR REPLACE INTO Products VALUES 
  (1, 'Hammer', 9.99),
  (2, 'Nails', 1.49),
  (3, 'Saw', 11.34),
  (1, 'Wrench', 37.00),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products; 

Výsledek:

ProductId Název produktu Cena ---------- ----------- ----------1 Klíč 37,0 2 hřebíky 1,49 3 Pila 11,34 5 Sekáč 23,0 6 Obvaz 120,0 

V tomto příkladu byl konflikt s primárním klíčem (zkoušel jsem vložit dva řádky se stejným ProductId ). REPLACE možnost způsobila, že druhá nahradila první.

Vrácení zpět

Další možností je použít ROLLBACK .

Tato volba zruší aktuální příkaz SQL s chybou SQLITE_CONSTRAINT a vrátí aktuální transakci zpět. Pokud není aktivní žádná transakce (kromě implikované transakce, která je vytvořena při každém příkazu), funguje stejně jako ABORT algoritmu.

Zde je příklad, který používá více INSERT OR ROLLBACK výpisy v rámci transakce.

DELETE FROM Products;

BEGIN TRANSACTION;
INSERT OR ROLLBACK INTO Products VALUES (1, 'Hammer', 9.99);
INSERT OR ROLLBACK INTO Products VALUES (2, NULL, 1.49);
INSERT OR ROLLBACK INTO Products VALUES (3, 'Saw', 11.34);
INSERT OR ROLLBACK INTO Products VALUES (4, 'Wrench', 37.00);
INSERT OR ROLLBACK INTO Products VALUES (5, 'Chisel', 23.00);
INSERT OR ROLLBACK INTO Products VALUES (6, 'Bandage', 120.00);
COMMIT;
  
SELECT * FROM Products; 

Zde je úplný výstup z mého terminálu, když to spustím:

sqlite> DELETE FROM Products;sqlite> sqlite> ZAČÁTEK TRANSAKCI;sqlite> INSERT NEBO ROLLBACK DO HODNOT produktů (1, 'Hammer', 9,99);sqlite> INSERT OR ROLLBACK DO Products VALUES (2, NULL); 1,49 NULL); Chyba:Omezení NOT NULL selhalo:Products.ProductNamesqlite> INSERT OR ROLLBACK INTO Products VALUES (3, 'Saw', 11.34);sqlite> INSERT OR ROLLBACK INTO Products VALUES (4, 'Wrench', 37.00);sqERT ROLLBACK> INSERT INTO Products VALUES (5, 'Chisel', 23.00);sqlite> INSERT OR ROLLBACK INTO Products VALUES (6, 'Bandage', 120.00);sqlite> COMMIT;Chyba:nelze potvrdit - žádná transakce není aktivnísqlite> sqlite> SELECT * FROM Products;ProductId ProductName Cena ---------- ----------- ----------3 Pila 11,34 4 Klíč 37,0 5 Sekáč 23,0 6 Bandáž 120,0  

Takže došlo k porušení omezení a poté transakci odvolala. Poté byly zpracovány následující řádky a poté COMMIT bylo nalezeno klíčové slovo. V té době již byla transakce vrácena zpět, a tak jsme dostali další chybu, která nám sdělovala, že žádná transakce nebyla aktivní.

Zde je to, co se stane, když jej odstraním z transakce.

DELETE FROM Products;

INSERT OR ROLLBACK INTO Products VALUES (1, 'Hammer', 9.99);
INSERT OR ROLLBACK INTO Products VALUES (2, NULL, 1.49);
INSERT OR ROLLBACK INTO Products VALUES (3, 'Saw', 11.34);
INSERT OR ROLLBACK INTO Products VALUES (4, 'Wrench', 37.00);
INSERT OR ROLLBACK INTO Products VALUES (5, 'Chisel', 23.00);
INSERT OR ROLLBACK INTO Products VALUES (6, 'Bandage', 120.00);
  
SELECT * FROM Products; 

Zde je úplný výstup z mého terminálu, když to spustím:

sqlite> DELETE FROM Products;sqlite> sqlite> INSERT OR ROLLBACK INTO Products VALUES (1, 'Hammer', 9.99);sqlite> INSERT OR ROLLBACK INTO Products VALUES (2, NULL, 1.49);Chybové omezení:NOT NULL selhalo:Products.ProductNamesqlite> INSERT OR ROLLBACK INTO Products VALUES (3, 'Saw', 11.34);sqlite> INSERT OR ROLLBACK INTO Products VALUES (4, 'Wrench', 37.00);sqlite> INSERT OR ROLLBACK INTO , 'Chisel', 23.00);sqlite> VLOŽIT NEBO VRÁTIT DO HODNOT produktů (6, 'Bandage', 120,00);sqlite> sqlite> SELECT * FROM Products;ProductId ProductName Cena ---------- -- --------- ----------1 Kladivo 9,99 3 Pila 11,34 4 Klíč 37,0 5 Sekáč 23,0 6 Obvaz 120,0 

V tomto případě to fungovalo jako ABORT .

Pro potvrzení je zde stejné prohlášení pomocí ABORT místo ROLLBACK .

DELETE FROM Products;

INSERT OR ABORT INTO Products VALUES (1, 'Hammer', 9.99);
INSERT OR ABORT INTO Products VALUES (2, NULL, 1.49);
INSERT OR ABORT INTO Products VALUES (3, 'Saw', 11.34);
INSERT OR ABORT INTO Products VALUES (4, 'Wrench', 37.00);
INSERT OR ABORT INTO Products VALUES (5, 'Chisel', 23.00);
INSERT OR ABORT INTO Products VALUES (6, 'Bandage', 120.00);
  
SELECT * FROM Products; 

Zde je úplný výstup z mého terminálu, když to spustím:

sqlite> DELETE FROM Products;sqlite> sqlite> INSERT OR ABORT INTO Products VALUES (1, 'Hammer', 9.99);sqlite> INSERT OR ABORT INTO Products VALUES (2, NULL, 1.49);Chyba:NOT NULL omezení selhalo:Products.ProductNamesqlite> INSERT OR ABORT INTO Products VALUES (3, 'Saw', 11.34);sqlite> INSERT OR ABORT INTO Products VALUES (4, 'Wrench', 37.00);sqlite> INSERT OR ABORT INTO Products VALUES , 'Chisel', 23.00);sqlite> INSERT NEBO ABORT INTO Products VALUES (6, 'Bandage', 120.00);sqlite> sqlite> SELECT * FROM Products;ProductId ProductName Cena ----------- -- --------- ----------1 Kladivo 9,99 3 Pila 11,34 4 Klíč 37,0 5 Sekáč 23,0 6 Obvaz 120,0 


  1. Vložte obrázek do databáze postgresql

  2. Funkce Concat nefunguje - neplatný počet argumentů

  3. Android sqlite, limit počtu řádků v databázi

  4. MySQL přidat jedinečné omezení