SQLite
 sql >> Teknologi Basis Data >  >> RDS >> SQLite

Menangani Konflik Kunci Utama saat Memasukkan Data di SQLite

SQLite memiliki klausa ekstensi SQL non-standar yang disebut ON CONFLICT yang memungkinkan kita untuk menentukan bagaimana menangani konflik kendala.

Secara khusus, klausa berlaku untuk UNIQUE , NOT NULL , CHECK , dan PRIMARY KEY kendala.

Artikel ini memberikan contoh bagaimana klausa ini dapat digunakan untuk menentukan cara menangani konflik batasan kunci utama.

Dengan "konflik kendala kunci utama", maksud saya ketika Anda mencoba memasukkan nilai duplikat ke dalam kolom kunci utama. Secara default, ketika Anda mencoba melakukan ini, operasi akan dibatalkan dan SQLite akan mengembalikan kesalahan.

Tetapi Anda dapat menggunakan ON CONFLICT klausa untuk mengubah cara SQLite menangani situasi ini.

Salah satu opsi adalah menggunakan klausa ini di CREATE TABLE pernyataan saat membuat tabel. Melakukannya akan menentukan bagaimana semua INSERT operasi diperlakukan.

Pilihan lainnya adalah menggunakan klausa pada INSERT pernyataan setiap kali Anda mencoba memasukkan data ke dalam tabel. Ini memungkinkan Anda untuk memanfaatkan klausa bahkan ketika tabel tidak dibuat dengannya. Saat Anda menggunakan opsi ini, sintaksnya berbeda; Anda menggunakan OR bukannya ON CONFLICT .

Contoh di halaman ini menggunakan opsi kedua – saya membuat tabel tanpa ON CONFLICT klausa, dan saya malah menentukan OR pada INSERT pernyataan.

Tabel Contoh

Mari buat tabel sederhana dan tambahkan satu baris.

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

INSERT INTO Products VALUES (1, 'Hammer', 8.00);

SELECT * FROM Products;

Hasil:

ProductId   ProductName  Price     
----------  -----------  ----------
1           Hammer       8.0       

Saat ini kami memiliki satu baris, dengan ProductId dari 1 .

Sekarang kita dapat menjalankan berbagai skenario memasukkan data ke dalam tabel yang melanggar batasan kunci utama.

Contoh 1 – Abort (Perilaku Default)

Seperti yang disebutkan, perilaku default untuk SQLite adalah membatalkan INSERT operasi dan mengembalikan kesalahan.

INSERT INTO Products VALUES (1, 'Wrench', 12.50);

Hasil:

Error: UNIQUE constraint failed: Products.ProductId

Kesalahan dikembalikan dan tidak ada yang dimasukkan.

Ini sama dengan menggunakan OR ABORT pilihan.

INSERT OR ABORT INTO Products VALUES (1, 'Wrench', 12.50);

Hasil:

Error: UNIQUE constraint failed: Products.ProductId

Kami dapat memverifikasi bahwa tidak ada yang dimasukkan dengan menjalankan SELECT pernyataan terhadap meja.

SELECT * FROM Products;

Hasil:

ProductId   ProductName  Price     
----------  -----------  ----------
1           Hammer       8.0       

Kita dapat melihat bahwa tabel hanya berisi baris asli.

Contoh 2 – Abaikan

Salah satu alternatifnya adalah membuat SQLite mengabaikan baris yang menyinggung. Dengan kata lain, ia akan melewati baris dan melanjutkan pemrosesan baris berikutnya.

Untuk melakukannya dalam INSERT . Anda pernyataan, gunakan OR IGNORE .

Efeknya adalah INSERT operasi berhasil, tetapi tanpa baris yang melanggar batasan kunci utama.

INSERT OR IGNORE INTO Products VALUES 
  (1, 'Hammer', 12.00),
  (2, 'Nails', 2.50),
  (3, 'Saw', 10.50),
  (1, 'Wrench', 22.50),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products;

Hasil:

ProductId   ProductName  Price     
----------  -----------  ----------
1           Hammer       8.0       
2           Nails        2.5       
3           Saw          10.5      
5           Chisel       23.0      
6           Bandage      120.0     

Dalam hal ini saya mencoba menyisipkan dua baris baru dengan ID yang sudah ada di tabel, sehingga kedua baris tersebut dilewati.

Contoh 3 – Ganti

Pilihan lain yang Anda miliki adalah mengganti baris asli dengan baris baru.

Dengan kata lain, Anda akan menimpa data yang ada dengan data baru Anda.

Untuk melakukannya, gunakan OR REPLACE .

INSERT OR REPLACE INTO Products VALUES 
  (1, 'Hammer', 12.00),
  (2, 'Nails', 2.50),
  (3, 'Saw', 10.50),
  (1, 'Wrench', 22.50),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products;

Hasil:

ProductId   ProductName  Price     
----------  -----------  ----------
1           Wrench       22.5      
2           Nails        2.5       
3           Saw          10.5      
5           Chisel       23.0      
6           Bandage      120.0     

Dalam hal ini sebagian besar baris adalah sama, sehingga berisi data yang sama setelah INSERT operasi. Namun, kita dapat melihat bahwa baris pertama telah diperbarui untuk menggunakan nilai dalam INSERT saya penyataan.

Kita juga dapat melihat bahwa itu menggunakan kumpulan nilai kedua (melihat dua berbagi ProductId yang sama ).

Jadi efeknya seperti UPDATE pernyataan dan INSERT pernyataan digabungkan.

Contoh 4 – Kembalikan

Pilihan lain adalah dengan menggunakan ROLLBACK pilihan.

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.

Membayar untuk memperhatikan bagaimana opsi ini bekerja. 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', 8.00);
INSERT OR ROLLBACK INTO Products VALUES (2, 'Nails', 2.50);
INSERT OR ROLLBACK INTO Products VALUES (3, 'Saw', 10.50);
INSERT OR ROLLBACK INTO Products VALUES (1, 'Wrench', 22.50);
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> BEGIN TRANSACTION;
sqlite> INSERT OR ROLLBACK INTO Products VALUES (1, 'Hammer', 8.00);
sqlite> INSERT OR ROLLBACK INTO Products VALUES (2, 'Nails', 2.50);
sqlite> INSERT OR ROLLBACK INTO Products VALUES (3, 'Saw', 10.50);
sqlite> INSERT OR ROLLBACK INTO Products VALUES (1, 'Wrench', 22.50);
Error: UNIQUE constraint failed: Products.ProductId
sqlite> INSERT OR ROLLBACK INTO Products VALUES (5, 'Chisel', 23.00);
sqlite> INSERT OR ROLLBACK INTO Products VALUES (6, 'Bandage', 120.00);
sqlite> COMMIT;
Error: cannot commit - no transaction is active
sqlite>   
sqlite> SELECT * FROM Products;
ProductId   ProductName  Price     
----------  -----------  ----------
5           Chisel       23.0      
6           Bandage      120.0     
sqlite> 

Pada dasarnya yang terjadi di sini adalah, telah sampai pada pelanggaran batasan, kemudian membatalkan transaksi. Kemudian dua 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', 8.00);
INSERT OR ROLLBACK INTO Products VALUES (2, 'Nails', 2.50);
INSERT OR ROLLBACK INTO Products VALUES (3, 'Saw', 10.50);
INSERT OR ROLLBACK INTO Products VALUES (1, 'Wrench', 22.50);
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', 8.00);
sqlite> INSERT OR ROLLBACK INTO Products VALUES (2, 'Nails', 2.50);
sqlite> INSERT OR ROLLBACK INTO Products VALUES (3, 'Saw', 10.50);
sqlite> INSERT OR ROLLBACK INTO Products VALUES (1, 'Wrench', 22.50);
Error: UNIQUE constraint failed: Products.ProductId
sqlite> INSERT OR ROLLBACK INTO Products VALUES (5, 'Chisel', 23.00);
sqlite> INSERT OR ROLLBACK INTO Products VALUES (6, 'Bandage', 120.00);
sqlite>   
sqlite> SELECT * FROM Products;
ProductId   ProductName  Price     
----------  -----------  ----------
1           Hammer       8.0       
2           Nails        2.5       
3           Saw          10.5      
5           Chisel       23.0      
6           Bandage      120.0     
sqlite>

Dalam hal ini, ini berfungsi seperti ABORT .

Untuk mendemonstrasikan ini, berikut pernyataan yang sama menggunakan ABORT bukannya ROLLBACK .

DELETE FROM Products;

INSERT OR ABORT INTO Products VALUES (1, 'Hammer', 8.00);
INSERT OR ABORT INTO Products VALUES (2, 'Nails', 2.50);
INSERT OR ABORT INTO Products VALUES (3, 'Saw', 10.50);
INSERT OR ABORT INTO Products VALUES (1, 'Wrench', 22.50);
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 OR ABORT INTO Products VALUES (1, 'Hammer', 8.00);
sqlite> INSERT OR ABORT INTO Products VALUES (2, 'Nails', 2.50);
sqlite> INSERT OR ABORT INTO Products VALUES (3, 'Saw', 10.50);
sqlite> INSERT OR ABORT INTO Products VALUES (1, 'Wrench', 22.50);
Error: UNIQUE constraint failed: Products.ProductId
sqlite> INSERT OR ABORT INTO Products VALUES (5, 'Chisel', 23.00);
sqlite> INSERT OR ABORT INTO Products VALUES (6, 'Bandage', 120.00);
sqlite>   
sqlite> SELECT * FROM Products;
ProductId   ProductName  Price     
----------  -----------  ----------
1           Hammer       8.0       
2           Nails        2.5       
3           Saw          10.5      
5           Chisel       23.0      
6           Bandage      120.0     
sqlite> 

Opsi Gagal

FAIL opsi membatalkan pernyataan SQL saat ini dengan kesalahan SQLITE_CONSTRAINT. Tetapi opsi ini tidak membatalkan perubahan sebelumnya dari pernyataan SQL yang gagal dan juga tidak mengakhiri transaksi.

DELETE FROM Products;

INSERT OR FAIL INTO Products VALUES 
  (1, 'Hammer', 8.00),
  (2, 'Nails', 2.50),
  (3, 'Saw', 10.50),
  (1, 'Wrench', 22.50),
  (5, 'Chisel', 23.00),
  (6, 'Bandage', 120.00);

SELECT * FROM Products;

Hasil:

ProductId   ProductName  Price     
----------  -----------  ----------
1           Hammer       8.0       
2           Nails        2.5       
3           Saw          10.5      

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Subkueri SQLite

  2. SQLite JSON_OBJECT()

  3. Mengkloning Database SQLite

  4. Mengaitkan tabel menggunakan database Room di Android Studio

  5. SQLite MAX