Polecenie "Insert if not exists" w SQLite

Mam bazę danych SQLite. Próbuję wstawić wartości (users_id, lessoninfo_id) w tabeli bookmarks, tylko wtedy, gdy oba nie istnieją wcześniej w wierszu.

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

To daje błąd mówiąc:

Błąd Db w pobliżu składni where.

Author: Tamás Sengel, 2013-10-12

5 answers

Jeśli masz tabelę o nazwie memos, która ma dwie kolumny id i text powinieneś być w stanie zrobić tak:

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

Jeśli rekord zawiera już wiersz, w którym {[2] } jest równy 'text to insert' i id jest równy 5, wtedy operacja insert zostanie zignorowana.

Nie wiem, czy to zadziała dla Twojego konkretnego zapytania, ale być może daje Ci podpowiedź, jak postępować.

Radziłbym zamiast tego zaprojektować tabelę tak, aby żadne duplikaty nie były dozwolone jako wyjaśnione w @CLs answer poniżej.

 87
Author: Cyclonecode,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-13 06:12:18

Jeśli nigdy nie chcesz mieć duplikatów, powinieneś zadeklarować to jako ograniczenie tabeli:

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

(Klucz główny nad obiema kolumnami miałby ten sam efekt.)

Można wtedy powiedzieć bazie danych, że chcesz po cichu ignorować rekordy, które naruszałyby takie ograniczenie :

INSERT OR IGNORE INTO bookmarks(users_id, lessoninfo_id) VALUES(123, 456)
 335
Author: CL.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-13 08:10:18

Dla unikalnej kolumny, użyj tego:

INSERT OR REPLACE INTO table () values();

Aby uzyskać więcej informacji, zobacz: sqlite.org/lang_insert

 5
Author: Ali Bagheri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-13 07:25:48
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;
To najszybsza droga.

Dla niektórych innych silników SQL, możesz użyć tabeli atrapy zawierającej 1 rekord. e. g:

select 1, 167 from ONE_RECORD_DUMMY_TABLE
 2
Author: suat dmk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-30 08:10:48
INSERT INTO Database.dbo.Table
     SELECT *
       FROM Database.dbo.Table
      WHERE ID not in (select ID from Database.dbo.Table)
 -2
Author: Almamun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-26 04:50:04