【问题标题】:sqlite3_step returns SQLITE_CONSTRAINTsqlite3_step 返回 SQLITE_CONSTRAINT
【发布时间】:2013-09-02 21:45:11
【问题描述】:

我的 iOS 应用程序中有一个本地 SQLite3 数据库。

通常一切都按需要运行,但有时当我尝试 insert 将新记录添加到我的表中时,我会收到一个奇怪的错误 (SQLITE_CONSTRAINT),调用 sqlite3_step(statement) 方法。这发生在表被删除并重新创建一次之后。(是的,我需要删除表并重新创建,而不仅仅是删除我的所有记录)。


这是我创建表格的方式。

CREATE TABLE MyTable (
reference text PRIMARY KEY not null collate nocase, 
value text not null collate nocase)

我的表没有任何手动创建的索引,只是自动生成了唯一索引"sqlite_autoindex_mytable_1"。当我阅读here(lang_creatable) 时,这是正常情况。


这里有一些代码:

sqlite3_stmt *statement;
int result = sqlite3_prepare_v2(database, [sqlString UTF8String], -1, &statement, NULL);
if (result == SQLITE_OK) {

   int sql_result = sqlite3_step(statement);
   // here is receive sql_result == SQLITE_CONSTRAINT (19)
}

问题不一定出在 sql 查询字符串中。正如我还读到的,当我尝试插入一些与已经存在的具有相同主键的记录时,我会收到此错误。就我而言,我有一个空表并收到此错误。

那么问题是什么会导致出现SQLITE_CONSTRAINT 错误?删除表后唯一索引不被删除还能包含一些信息吗?

【问题讨论】:

    标签: ios sql sqlite indexing


    【解决方案1】:

    您应该查看sqlite3_errmsg 返回的错误消息,它会准确地告诉您哪个约束失败以及插入失败的原因。它可能会报告

    • “列引用不是唯一的” - 当您尝试插入的 reference 值已存在于表中时,您会得到此信息;或

    • "value may not be NULL" - 当您尝试将NULL 插入定义为NOT NULL 的列时,您会得到此信息。

    这两个错误都会以SQLITE_CONSTRAINT 的返回码返回。只有查看sqlite3_errmsg,才能有效诊断问题根源。

    坦率地说,我假设前者是问题所在(您插入的 reference 已经存在于表中),但在您查看 sqlite3_errmsg 之前,我们只是在猜测。

    int result;
    
    if ((result = sqlite3_prepare_v2(database, [sql UTF8String], -1, &statement, NULL)) != SQLITE_OK) {
        NSLog(@"%s: sqlite3_prepare error: %s (%d)", __FUNCTION__, sqlite3_errmsg(database), result);
    }
    
    if ((result = sqlite3_step(statement)) != SQLITE_DONE) {
        NSLog(@"%s: step error: %s (%d)", __FUNCTION__, sqlite3_errmsg(database), result);
    }
    else
        NSLog(@"success");
    
    sqlite3_finalize(statement);
    

    查看sqlite3_errmsg,它会准确地告诉您出了什么问题。然后,您可能想要检查您尝试插入的值并将其与表中已有的值以及您定义的约束 (NOT NULL) 进行比较。

    【讨论】:

    • 感谢您的回答,我已经测试过添加 sqlite3_errormsg。结果,它向我显示步骤错误:列引用不是唯一的 (19)。但是正如我在一个问题中所问的那样,当我有一个空表时,怎么可能收到此错误消息?
    • @George 这意味着您的表不是为空的。
    • 可能听起来很有趣,但它是空的。正如我在问题中所说。首先我放下表格,然后创建它。在这两个操作之后,我尝试插入一些记录并收到错误,我还查看了 SQLite 管理器,看到表被删除,一步一步调试,发现它是空的
    • @George 不看代码很难说。在没有代码的情况下,我们都会自然而然地怀疑一些简单的逻辑错误(例如,从包中打开数据库,不检查来自DROP 命令的SQLITE_OK 响应等),这些错误会阻止记录像您一样被实际删除认为他们是。如果最坏的情况发生,也许你应该做一个表的REINDEX 或整个数据库的PRAGMA integrity_check
    • 我仍然找不到问题的原因,但是如果我重新创建表后重新连接到数据库,它就会解决。所以我让 sqlite3_close 比 sqlite3_open 更重要,之后我没有收到任何错误。我认为可能存在 SQLite 连接中的缓存之类的东西,它没有正确更新。所以我结束了这个问题。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    • 2015-06-10
    • 2014-04-10
    相关资源
    最近更新 更多