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:
ABORT
FAIL
IGNORE
REPLACE
ROLLBACK
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
UNIQUE
atauPRIMARY KEY
pelanggaran kendala terjadi,,REPLACE
opsi 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 NULL
pelanggaran kendala terjadi, itu menggantikanNULL
nilai dengan nilai default untuk kolom tersebut, atau jika kolom tidak memiliki nilai default, makaABORT
algoritma yang digunakan. - Jika
CHECK
kendala atau pelanggaran batasan kunci asing terjadi, laluREPLACE
bekerja 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
COMMIT
kata 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
ABORT
bukannyaROLLBACK
.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