SQLite'de “Ekle yoksa” ifadesi


143

Bir SQLite veritabanım var. Yalnızca bir satırda daha önce yoksa değerleri ( users_id, lessoninfo_id) tabloya eklemek çalışıyorum bookmarks.

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+")))

Bu bir hata veriyor:

sözdiziminin yakınında db hatası.

Yanıtlar:


138

İki sütuna sahip notlar adında bir tablonuz varsa idve textbunu yapabilmeniz gerekir:

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');

Bir kayıt zaten text'eklenecek metne' ideşit ve 5'e eşit bir satır içeriyorsa , ekleme işlemi yok sayılır.

Bu sizin özel sorgunuz için işe yarayacak mı bilmiyorum, ama belki de nasıl devam etmek için bir ipucu vermek.

Bunun yerine, @CLs answeraşağıda açıklandığı gibi kopyalara izin verilmeyecek şekilde masanızı tasarlamanızı tavsiye ederim .


436

Hiçbir zaman kopya istemiyorsanız, bunu bir tablo kısıtı olarak bildirmelisiniz:

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

(Her iki sütunun üzerindeki birincil anahtar da aynı etkiye sahip olacaktır.)

Daha sonra veritabanına, böyle bir kısıtlamayı ihlal edecek kayıtları sessizce yoksaymak istediğinizi söylemek mümkündür :

INSERT OR IGNORE INTO bookmarks(users_id, lessoninfo_id) VALUES(123, 456)

12
Daha sonra yeni eklenen satırın veya zaten var olan satırın kimliğini almanın en iyi yolu nedir, böylece bunu yabancı anahtar olan başka bir tabloya ekleyebilir miyim? Örneğin, iki masam var person (id, name unique)ve cat (person_id, name unique)çok sayıda çift eklemek istiyorum (person_name, cat_name)?
Aur Saraf

2
Mevcut bir satırın kimliğini okumak sadece bir SELECT sorgusu ile mümkündür. Ama bu farklı bir soru.
CL.

1
Belki ekleyerek ON CONFLICT IGNOREiçin CREATE TABLEolmak biraz daha kullanışlı olur
defhlt

1
@ rightaway717 "Yoksay" hiçbir şeyin olmadığı anlamına gelir; bu sorunun güncelleme ile ilgisi yoktur.
CL.

1
@ Hack06 Android eki () farklı davranır; bunu insertOrThrow () veya insertWithOnConflict () ile değiştirmelisiniz .
CL.

21

Benzersiz bir sütun için şunu kullanın:

INSERT OR REPLACE INTO table () values();

Daha fazla bilgi için bkz. Sqlite.org/lang_insert


Bu benim için işe yaramıyor. her zaman my_table (col1, col2) değerlerine ('1', '2') ekleme veya değiştirme gibi ekler; 1 2'nin birden çok satırını ekleyecek
Peter Moore

Kısıtlama yerine Unique(col1,col2)getirilirse ve ayrıca col3'ünüz varsa iyi çalıştığını da ekleyebilirim , çünkü bu, col3'ü yeni değere güncelleyecek bir ekleme veya yoksayma başarısız olur. insert or replace into my_table values('1','2','5')bir sıranın yerine geçer'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;

Bu en hızlı yol.

Diğer bazı SQL motorları için, 1 kayıt içeren bir Dummy tablosu kullanabilirsiniz. Örneğin:

select 1, 167 from ONE_RECORD_DUMMY_TABLE
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.