SQLite中的"如果不存在则插入"语句

use*_*638 115 sqlite constraints sql-insert

我有一个SQLite数据库.我试图在表中插入值(users_id,lessoninfo_id),前提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+")))
Run Code Online (Sandbox Code Playgroud)

这给出了一个错误说:

db error附近的语法.

CL.*_*CL. 399

如果您从不想要重复项,则应将其声明为表约束:

CREATE TABLE bookmarks(
    users_id INTEGER,
    lessoninfo_id INTEGER,
    UNIQUE(users_id, lessoninfo_id)
);
Run Code Online (Sandbox Code Playgroud)

(两列上的主键都会产生相同的效果.)

然后可以告诉数据库您要静默忽略违反此类约束的记录:

INSERT OR IGNORE INTO bookmarks(users_id, lessoninfo_id) VALUES(123, 456)
Run Code Online (Sandbox Code Playgroud)

  • 然后获取新插入的行或已存在的行的ID的最佳方法是什么,所以我可以将它插入到另一个具有外键的表中?例如,我有两个表`person(id,name unique)`和`cat(person_id,name unique)`我想插入很多对`(person_name,cat_name)`? (10认同)
  • 请记住,使用“INSERT IGNORE”,如果查询失败,您将失去洞察力,这可能意味着您正在悄悄地丢失数据。这不是数据库的设计目的。仅当您完全了解后果时才使用:`INSERT IGNORE`。如果可能,请使用“ON CONFLICT DO NOTHING”(需要 SQLite 3.24+),对于任何较旧的 SQLite,“INSERT INTO ... SELECT ... WHERE NOT EXISTS(SELECT 1 ... FROM WHERE ...)”更安全……虽然相当麻烦。 (5认同)
  • 只有使用SELECT查询才能读取现有行的ID.但这是一个不同的问题. (2认同)
  • 也许将“ON CONFLICT IGNORE”添加到“CREATE TABLE”会更方便一些 (2认同)

Cyc*_*ode 115

如果你有一个名为memos的表,它有两列id,text你应该能够这样做:

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');
Run Code Online (Sandbox Code Playgroud)

如果记录已包含text等于"要插入的文本"且id等于5的行,则将忽略插入操作.

我不知道这是否适用于您的特定查询,但它可能会提示您如何继续.

我建议您改为设计表格,以便不允许重复,@CLs answer如下所述.


Ali*_*eri 16

对于唯一列,请使用以下命令:

INSERT OR REPLACE INTO table () values();
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅:sqlite.org/lang_insert

  • 这对我不起作用。它总是像插入或替换一样插入到 my_table (col1, col2) value('1','2'); 将添加多行 1 2 (3认同)
  • 我可能会补充一点,如果约束设置为“Unique(col1,col2)”并且您还有 col3,那么它确实可以很好地工作,因为插入或忽略将失败,这会将 col3 更新为新值。`insert or Replace into my_table values('1','2','5')` 替换行 `'1','2','3'` (2认同)

小智 7

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;
Run Code Online (Sandbox Code Playgroud)

这是最快的方法。

对于某些其他 SQL 引擎,您可以使用包含 1 条记录的虚拟表。例如:

select 1, 167 from ONE_RECORD_DUMMY_TABLE
Run Code Online (Sandbox Code Playgroud)