【问题标题】:"Insert if not exists" statement in SQLiteSQLite 中的“如果不存在则插入”语句
【发布时间】:2013-10-20 15:34:16
【问题描述】:

我有一个 SQLite 数据库。我正在尝试在表 bookmarks 中插入值(users_idlessoninfo_id),前提是两者之前都不存在。

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

这给出了一个错误提示:

where 语法附近出现 db 错误。

【问题讨论】:

    标签: sqlite constraints sql-insert


    【解决方案1】:

    如果你不想有重复,你应该把它声明为一个表约束:

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

    (两列上的主键将具有相同的效果。)

    然后可以告诉数据库你想silently ignore records that would violate such a constraint

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

    【讨论】:

    • 获取新插入行的 ID 或已经存在的行的 ID 的最佳方法是什么,以便我可以将其插入到另一个具有该外键的表中?例如我有两张表person (id, name unique)cat (person_id, name unique),我想插入很多对(person_name, cat_name)?
    • 只有使用 SELECT 查询才能读取现有行的 ID。但这是一个不同的问题。
    • 或许将ON CONFLICT IGNORE 添加到CREATE TABLE 会更方便一些
    • @rightaway717 “忽略”表示什么都没有发生;这个问题与更新无关。
    • @Hack06 Android 的 insert() 行为不同;您应该将其替换为 insertOrThrow()insertWithOnConflict()
    【解决方案2】:

    如果您有一个名为 memos 的表,它有两列 idtext,您应该可以这样做:

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

    如果记录已经包含text 等于“要插入的文本”且id 等于5 的行,则插入操作将被忽略。

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

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

    【讨论】:

      【解决方案3】:

      对于一个唯一的列,使用这个:

      INSERT OR REPLACE INTO table () values();
      

      欲了解更多信息,请参阅:sqlite.org/lang_insert

      【讨论】:

      • 这对我不起作用。它总是像插入或替换一样插入到 my_table (col1, col2) values('1','2');将添加多行 1 2
      • 我可能会补充一点,如果将约束设置到位 Unique(col1,col2) 并且您也有 col3,它会很好地工作,因为插入或忽略将失败,这会将 col3 更新为新值。 insert or replace into my_table values('1','2','5') 替换一行 '1','2','3'
      【解决方案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;
      

      这是最快的方法。

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

      select 1, 167 from ONE_RECORD_DUMMY_TABLE
      

      【讨论】:

        猜你喜欢
        • 2021-10-14
        • 1970-01-01
        • 2011-01-13
        • 1970-01-01
        • 2015-03-31
        • 2013-07-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多