Gaya Tanya Jawab
Nah, setelah meneliti dan berjuang dengan masalah selama berjam-jam, saya menemukan bahwa ada dua cara untuk melakukannya, tergantung pada struktur tabel Anda dan jika Anda mengaktifkan pembatasan kunci asing untuk menjaga integritas. Saya ingin membagikan ini dalam format yang bersih untuk menghemat waktu kepada orang-orang yang mungkin berada dalam situasi saya.
Opsi 1: Anda mampu menghapus baris tersebut
Dengan kata lain, Anda tidak memiliki kunci asing, atau jika Anda memilikinya, mesin SQLite Anda dikonfigurasi sehingga tidak ada pengecualian integritas. Cara untuk pergi adalah INSERT OR REPLACE . Jika Anda mencoba memasukkan / memperbarui pemain yang ID-nya sudah ada, mesin SQLite akan menghapus baris itu dan memasukkan data yang Anda berikan. Sekarang pertanyaannya muncul: apa yang harus dilakukan agar ID lama tetap terkait?
Katakanlah kita ingin UPSERT dengan data user_name = 'steven' dan age = 32.
Lihat kode ini:
INSERT INTO players (id, name, age)
VALUES (
coalesce((select id from players where user_name='steven'),
(select max(id) from drawings) + 1),
32)
Triknya sedang menyatu. Ia mengembalikan id pengguna 'steven' jika ada, dan sebaliknya, ia mengembalikan id baru yang baru.
Opsi 2: Anda tidak mampu menghapus baris tersebut
Setelah berkutat dengan solusi sebelumnya, saya menyadari bahwa dalam kasus saya itu bisa menghancurkan data, karena ID ini berfungsi sebagai kunci asing untuk tabel lain. Selain itu, saya membuat tabel dengan klausul ON DELETE CASCADE , yang berarti akan menghapus data secara diam-diam. Berbahaya.
Jadi, saya pertama kali memikirkan klausa IF, tetapi SQLite hanya memiliki CASE . Dan KASUS ini tidak dapat digunakan (atau setidaknya saya tidak mengelolanya) untuk melakukan satu kueri UPDATE jika SUDAH (pilih id dari pemain di mana user_name = 'steven'), dan MASUKKAN jika tidak. Tidak pergi.
Dan kemudian, akhirnya saya menggunakan kekerasan, dengan sukses. Logikanya adalah, untuk setiap UPSERT yang ingin Anda lakukan, pertama-tama lakukan INSERT ATAU IGNORE untuk memastikan ada baris dengan pengguna kami, lalu jalankan kueri UPDATE dengan data yang sama persis dengan yang Anda coba masukkan.
Data yang sama seperti sebelumnya: user_name = 'steven' dan age = 32.
-- make sure it exists
INSERT OR IGNORE INTO players (user_name, age) VALUES ('steven', 32);
-- make sure it has the right data
UPDATE players SET user_name='steven', age=32 WHERE user_name='steven';
Dan itu saja!
EDIT
Seperti yang telah dikomentari Andy, mencoba memasukkan terlebih dahulu dan kemudian memperbarui dapat menyebabkan pemicu pengaktifan lebih sering dari yang diharapkan. Menurut saya, ini bukan masalah keamanan data, tetapi memang benar bahwa mengaktifkan peristiwa yang tidak perlu tidak masuk akal. Oleh karena itu, solusi yang lebih baik adalah:
-- Try to update any existing row
UPDATE players SET age=32 WHERE user_name='steven';
-- Make sure it exists
INSERT OR IGNORE INTO players (user_name, age) VALUES ('steven', 32);