Instrucțiunea „Insert if not exists” în SQLite (Programare, Sqlite, Constrângeri, Sql Insert)

user2780638 a intrebat.

Am o bază de date SQLite. Încerc să inserez valori (users_id, lessoninfo_id) în tabelul bookmarks, numai dacă ambele nu există înainte într-un rând.

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

Acest lucru dă o eroare care spune:

db error near where syntax.

4 răspunsuri
Cyclonecode

Dacă aveți un tabel numit memos care are două coloane id și text ar trebui să puteți face așa:

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

Dacă o înregistrare conține deja un rând în care text este egal cu „text de inserat” și id este egal cu 5, atunci operațiunea de inserare va fi ignorată.

Nu știu dacă acest lucru va funcționa pentru interogarea dvs. particulară, dar poate că vă oferă un indiciu despre cum să procedați.

V-aș sfătui, în schimb, să vă proiectați tabelul astfel încât să nu fie permise duplicate, așa cum se explică în @CLs answer mai jos.

CL.

Dacă nu doriți să aveți niciodată duplicate, ar trebui să declarați acest lucru ca o constrângere de tabel:

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

(O cheie primară pe ambele coloane ar avea același efect).

Este apoi posibil să spuneți bazei de date că doriți să să ignorați în tăcere înregistrările care ar încălca o astfel de constrângere:

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

Comentarii

    18

  • Care este modalitatea optimă de a obține apoi ID-ul rândului nou introdus sau al celui deja existent, astfel încât să îl pot introduce într-un alt tabel care are o cheie externă la acesta? de exemplu, am două tabele person (id, name unique) și cat (person_id, name unique) și vreau să inserez o mulțime de perechi (person_name, cat_name)? –  > Por Aur Saraf.
  • Citirea ID-ului unui rând existent este posibilă numai cu o interogare SELECT. Dar aceasta este o altă întrebare. –  > Por CL..
  • Poate că adăugarea ON CONFLICT IGNORE la CREATE TABLE ar fi un pic mai la îndemână –  > Por defhlt.
  • @rightaway717 „Ignoră” înseamnă că nu se întâmplă nimic; această întrebare nu are nimic de-a face cu actualizarea. –  > Por CL..
  • @Hack06 Insert() de la Android se comportă diferit; ar trebui să îl înlocuiți cu insertOrThrow() sau insertWithOnConflict(). –  > Por CL..
Ali Bagheri

Pentru o coloană unică, utilizați acest lucru:

INSERT OR REPLACE INTO table () values();

Pentru mai multe informații, consultați: sqlite.org/lang_insert

Comentarii

  • Acest lucru nu funcționează pentru mine. întotdeauna se inserează ca în insert or replace into my_table (col1, col2) values(‘1′,’2’); va adăuga mai multe rânduri de 1 2 –  > Por Peter Moore.
  • Aș putea adăuga că funcționează bine dacă se aplică constrângerea Unique(col1,col2) și aveți, de asemenea, col3, deoarece o inserție sau o ignorare ar eșua în cazul în care acest lucru va actualiza col3 la noua valoare. insert or replace into my_table values('1','2','5') Înlocuiește un rând '1','2','3' –  > Por Peter Moore.
suat dmk
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;

Aceasta este cea mai rapidă metodă.

Pentru alte motoare SQL, puteți utiliza un tabel fictiv care conține 1 înregistrare.De ex:

select 1, 167 from ONE_RECORD_DUMMY_TABLE