SQLite memiliki ON CONFLICT klausa yang memungkinkan Anda menentukan cara menangani konflik kendala. Ini berlaku untuk UNIQUE , NOT NULL , CHECK , dan PRIMARY KEY batasan (tetapi bukan FOREIGN KEY kendala).
Ada lima opsi yang dapat Anda gunakan dengan klausa ini:
ABORTFAILIGNOREREPLACEROLLBACK
Artikel ini memberikan contoh dan penjelasan dari masing-masing opsi ini.
ON CONFLICT klausa digunakan dalam CREATE TABLE pernyataan, tetapi juga dapat digunakan saat memasukkan atau memperbarui data dengan mengganti ON CONFLICT dengan OR .
Saat Membuat Tabel
Seperti yang disebutkan, Anda dapat menggunakan ON CONFLICT saat Anda membuat tabel atau saat Anda memasukkan/memperbarui data.
Berikut ini contoh penggunaan ON CONFLICT pada saat membuat tabel.
CREATE TABLE Products(
ProductId INTEGER PRIMARY KEY,
ProductName NOT NULL ON CONFLICT IGNORE,
Price
);
Saat Anda menggunakan ON CONFLICT klausa, Anda menerapkannya pada batasan spesifik yang ingin Anda tangani. Dalam hal ini, saya menambahkan klausa ke NOT NULL kendala.
Dalam hal ini saya menentukan IGNORE , yang berarti, jika ada pelanggaran batasan, SQLite akan melewati baris tersebut dan melanjutkan pemrosesan.
Sekarang jika saya mencoba memasukkan NULL ke dalam ProductName kolom baris itu dilewati.
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; Hasil:
ProductId ProductName Harga ---------- ----------- ----------1 Palu 9,99 3 Gergaji 11,34 4 Kunci Pas 37,0 5 Pahat 23,0 6 Perban 120.0
Saat Memasukkan Data
Anda juga dapat menggunakan klausa ini saat memasukkan dan memperbarui data. Bedanya, Anda mengganti ON CONFLICT dengan OR .
Untuk mendemonstrasikannya, saya akan membuang tabel sebelumnya dan membuatnya lagi, tetapi tanpa ON CONFLICT klausa:
DROP TABLE IF EXISTS Products;
CREATE TABLE Products(
ProductId INTEGER PRIMARY KEY,
ProductName NOT NULL,
Price
);
Sekarang saya akan memasukkan data yang sama dan menggunakan OR IGNORE untuk melewati baris yang melanggar batasan.
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; Hasil:
ProductId ProductName Harga ---------- ----------- ----------1 Palu 9,99 3 Gergaji 11,34 4 Kunci Pas 37,0 5 Pahat 23,0 6 Perban 120.0
Jadi kita mendapatkan hasil yang sama seperti pada contoh sebelumnya.
Dalam contoh ini saya menggunakan IGNORE pilihan. Ini hanyalah salah satu dari lima opsi yang mungkin untuk klausa ini.
Di bawah ini adalah contoh penggunaan masing-masing dari lima opsi.
Batalkan
Opsi ini membatalkan pernyataan SQL saat ini dengan kesalahan SQLITE_CONSTRAINT dan membatalkan semua perubahan yang dibuat oleh pernyataan SQL saat ini; tetapi perubahan yang disebabkan oleh pernyataan SQL sebelumnya dalam transaksi yang sama dipertahankan dan transaksi tetap aktif.
Ini adalah perilaku default. Dengan kata lain, inilah yang terjadi selama pelanggaran batasan ketika Anda tidak menggunakan kode ON CONFLICT klausa.
Berikut adalah contoh yang terjadi saat Anda menentukan 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; Hasil:
Tidak ada hasil yang dikembalikan karena INSERT operasi dibatalkan, dan tabel karena itu kosong.
Inilah yang terjadi jika saya meletakkan setiap baris di INSERT-nya sendiri pernyataan dalam suatu transaksi.
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; Hasil:
ProductId ProductName Harga ---------- ----------- ----------1 Palu 9,99 3 Gergaji 11,34 4 Kunci Pas 37,0 5 Pahat 23,0 6 Perban 120.0
Gagal
FAIL opsi membatalkan pernyataan SQL saat ini dengan kesalahan SQLITE_CONSTRAINT. Tapi itu tidak membatalkan perubahan sebelumnya dari pernyataan SQL yang gagal dan juga tidak mengakhiri transaksi.
Ini contohnya.
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; Hasil:
ProductId ProductName Harga ---------- ----------- ----------1 Hammer 9.99
Ini dia dengan INSERT yang terpisah pernyataan dalam suatu transaksi.
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; Hasil:
ProductId ProductName Harga ---------- ----------- ----------1 Palu 9,99 3 Gergaji 11,34 4 Kunci Pas 37,0 5 Pahat 23,0 6 Perban 120.0
Abaikan
IGNORE opsi melewatkan satu baris yang berisi pelanggaran batasan dan terus memproses baris berikutnya dari pernyataan SQL seolah-olah tidak ada yang salah. Baris lain sebelum dan sesudah baris yang berisi pelanggaran kendala disisipkan atau diperbarui secara normal. Tidak ada kesalahan yang dikembalikan untuk keunikan, NOT NULL , dan UNIQUE kendala kesalahan saat opsi ini digunakan. Namun, opsi ini berfungsi seperti ABORT untuk kesalahan batasan kunci asing.
Contoh pertama di halaman ini menggunakan IGNORE , tapi ini dia lagi.
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; Hasil:
ProductId ProductName Harga ---------- ----------- ----------1 Palu 9,99 3 Gergaji 11,34 4 Kunci Pas 37,0 5 Pahat 23,0 6 Perban 120.0
Ganti
REPLACE opsi bekerja secara berbeda tergantung pada pelanggarannya:
- Bila
UNIQUEatauPRIMARY KEYpelanggaran kendala terjadi,,REPLACEopsi menghapus baris yang sudah ada sebelumnya yang menyebabkan pelanggaran batasan sebelum menyisipkan atau memperbarui baris saat ini dan perintah terus dijalankan secara normal. - Jika
NOT NULLpelanggaran kendala terjadi, itu menggantikanNULLnilai dengan nilai default untuk kolom tersebut, atau jika kolom tidak memiliki nilai default, makaABORTalgoritma yang digunakan. - Jika
CHECKkendala atau pelanggaran batasan kunci asing terjadi, laluREPLACEbekerja sepertiABORT.
Selain itu, jika menghapus baris untuk memenuhi batasan, hapus pemicu diaktifkan jika dan hanya jika pemicu rekursif diaktifkan.
Berikut adalah contoh yang menggunakan REPLACE pilihan.
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; Hasil:
ProductId ProductName Harga ---------- ----------- ----------1 Kunci Pas 37,0 2 Paku 1,49 3 Gergaji 11,34 5 Pahat 23,0 6 Perban 120.0
Dalam contoh ini, konfliknya adalah dengan kunci utama (saya mencoba memasukkan dua baris dengan ProductId yang sama ). REPLACE opsi menyebabkan yang kedua menggantikan yang pertama.
Kembalikan
Pilihan lain adalah menggunakan ROLLBACK .
Opsi ini membatalkan pernyataan SQL saat ini dengan kesalahan SQLITE_CONSTRAINT dan mengembalikan transaksi saat ini. Jika tidak ada transaksi yang aktif (selain transaksi tersirat yang dibuat pada setiap perintah) maka cara kerjanya sama dengan ABORT algoritma.
Berikut adalah contoh yang menggunakan beberapa INSERT OR ROLLBACK pernyataan dalam suatu transaksi.
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; Inilah output lengkap dari terminal saya ketika saya menjalankan ini:
sqlite> HAPUS DARI Produk;sqlite> sqlite> MULAI TRANSAKSI;sqlite> INSERT OR ROLLBACK INTO Products VALUES (1, 'Hammer', 9.99);sqlite> INSERT OR ROLLBACK INTO Products VALUES (2, NULL, 1.49); Kesalahan:batasan NOT NULL gagal: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 Products VALUES (5, 'Pahat', 23.00);sqlite> INSERT OR ROLLBACK INTO Products VALUES (6, 'Bandage', 120.00);sqlite> COMMIT;Error:tidak dapat melakukan - tidak ada transaksi yang aktifsqlite> sqlite> SELECT * FROM Produk;ProductId ProductName Harga ---------- ----------- ----------3 Saw 11,34 4 Kunci Pas 37.0 5 Pahat 23.0 6 Perban 120.0Jadi sampai pada pelanggaran batasan, lalu dibatalkan transaksinya. Kemudian baris berikutnya diproses dan kemudian
COMMITkata kunci ditemukan. Saat itu, transaksi telah dibatalkan dan kami mendapatkan kesalahan lain yang memberi tahu kami bahwa tidak ada transaksi yang aktif.Inilah yang terjadi jika saya menghapusnya dari transaksi.
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;Inilah output lengkap dari terminal saya ketika saya menjalankan ini:
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);Error:NOT NULL constraint gagal: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 Products VALUES (5 , 'Pahat', 23.00);sqlite> INSERT OR ROLLBACK INTO Products VALUES (6, 'Bandage', 120.00);sqlite> sqlite> SELECT * FROM Products;ProductId ProductName Price ---------- -- --------- ----------1 Palu 9,99 3 Gergaji 11,34 4 Kunci Pas 37.0 5 Pahat 23.0 6 Perban 120.0Dalam hal ini, ini berfungsi seperti
ABORT.Untuk mengonfirmasi, berikut pernyataan yang sama menggunakan
ABORTbukannyaROLLBACK.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;Inilah output lengkap dari terminal saya ketika saya menjalankan ini:
sqlite> DELETE FROM Products;sqlite> sqlite> INSERT ATAU ABORT INTO Products VALUES (1, 'Hammer', 9.99);sqlite> INSERT ATAU ABORT INTO Products VALUES (2, NULL, 1.49);Error:NOT NULL constraint gagal: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 (5 , 'Pahat', 23.00);sqlite> INSERT OR ABORT INTO Products VALUES (6, 'Bandage', 120.00);sqlite> sqlite> SELECT * FROM Products;ProductId ProductName Price ---------- -- --------- ----------1 Palu 9,99 3 Gergaji 11,34 4 Kunci Pas 37,0 5 Pahat 23,0 6 Perban 120,0