Pernyataan "Sisipkan jika tidak ada" di SQLite

152

Saya memiliki database SQLite. Saya mencoba memasukkan nilai ( users_id, lessoninfo_id) dalam tabel bookmarks, hanya jika keduanya tidak ada sebelumnya berturut-turut.

INSERT INTO bookmarks(users_id,lessoninfo_id) 
VALUES(
    (SELECT _id FROM Users WHERE User='"+$('#user_lesson').html()+"'),
        (SELECT _id FROM lessoninfo 
        WHERE Lesson="+lesson_no+" AND cast(starttime AS int)="+Math.floor(result_set.rows.item(markerCount-1).starttime)+") 
        WHERE NOT EXISTS (
            SELECT users_id,lessoninfo_id from bookmarks 
            WHERE users_id=(SELECT _id FROM Users 
            WHERE User='"+$('#user_lesson').html()+"') AND lessoninfo_id=(
                SELECT _id FROM lessoninfo
                WHERE Lesson="+lesson_no+")))

Ini memberikan kesalahan yang mengatakan:

kesalahan db dekat tempat sintaks.

pengguna2780638
sumber

Jawaban:

150

Jika Anda memiliki tabel bernama memo yang memiliki dua kolom iddan textAnda dapat melakukan seperti ini:

INSERT INTO memos(id,text) 
SELECT 5, 'text to insert' 
WHERE NOT EXISTS(SELECT 1 FROM memos WHERE id = 5 AND text = 'text to insert');

Jika record sudah berisi baris textyang sama dengan 'teks untuk disisipkan' dan idsama dengan 5, maka operasi penyisipan akan diabaikan.

Saya tidak tahu apakah ini akan berfungsi untuk kueri khusus Anda, tetapi mungkin ini memberi Anda petunjuk tentang cara melanjutkan.

Saya akan menyarankan agar Anda mendesain tabel Anda sehingga tidak ada duplikat yang diizinkan seperti yang dijelaskan di @CLs answerbawah ini.

Kode siklon
sumber
454

Jika Anda tidak pernah ingin memiliki duplikat, Anda harus mendeklarasikannya sebagai batasan tabel:

CREATE TABLE bookmarks(
    users_id INTEGER,
    lessoninfo_id INTEGER,
    UNIQUE(users_id, lessoninfo_id)
);

(Kunci utama di atas kedua kolom akan memiliki efek yang sama.)

Kemudian dimungkinkan untuk memberi tahu database bahwa Anda ingin mengabaikan rekaman secara diam-diam yang akan melanggar batasan seperti itu :

INSERT OR IGNORE INTO bookmarks(users_id, lessoninfo_id) VALUES(123, 456)
CL.
sumber
15
Apa cara optimal untuk mendapatkan ID dari baris yang baru disisipkan atau yang sudah ada, sehingga saya dapat memasukkannya ke tabel lain yang memiliki kunci asing untuk baris ini? misalnya saya memiliki dua tabel person (id, name unique)dan cat (person_id, name unique)dan saya ingin memasukkan banyak pasangan (person_name, cat_name)?
Aur Saraf
2
Membaca ID dari baris yang sudah ada hanya dimungkinkan dengan query SELECT. Tapi ini pertanyaan yang berbeda.
CL.
1
Mungkin menambahkan ON CONFLICT IGNOREke CREATE TABLEakan sedikit lebih praktis
defhlt
1
@ rightaway717 "Abaikan" berarti tidak ada yang terjadi; pertanyaan ini tidak ada hubungannya dengan pembaruan.
CL.
1
@ Hack06 Sisipan Android () berperilaku berbeda; Anda harus menggantinya dengan insertOrThrow () atau insertWithOnConflict () .
CL.
29

Untuk kolom unik, gunakan ini:

INSERT OR REPLACE INTO table () values();

Untuk informasi lebih lanjut, lihat: sqlite.org/lang_insert

Ali Bagheri
sumber
Ini tidak berhasil untuk saya. itu selalu menyisipkan seperti dalam menyisipkan atau mengganti ke my_table (col1, col2) values ​​('1', '2'); akan menambahkan beberapa baris 1 2
Peter Moore
Saya dapat menambahkan bahwa itu berfungsi dengan baik jika kendala diterapkan Unique(col1,col2)dan Anda juga memiliki col3, karena penyisipan atau pengabaian akan gagal di mana ini akan memperbarui col3 ke nilai baru. insert or replace into my_table values('1','2','5')menggantikan baris'1','2','3'
Peter Moore
4
insert into bookmarks (users_id, lessoninfo_id)

select 1, 167
EXCEPT
select user_id, lessoninfo_id
from bookmarks
where user_id=1
and lessoninfo_id=167;

Ini cara tercepat.

Untuk beberapa mesin SQL lainnya, Anda dapat menggunakan tabel Dummy yang berisi 1 record. misalnya:

select 1, 167 from ONE_RECORD_DUMMY_TABLE
suat dmk
sumber