【问题标题】:"database locked" error in ios while updating query更新查询时 ios 中的“数据库锁定”错误
【发布时间】:2013-07-31 12:27:12
【问题描述】:

我正在使用下面的代码更新查询,使用sqlite
但是我得到了"database is locked error"
我尝试搜索一些 SO 链接,并建议关闭数据库,但我再次这样做时遇到了同样的错误。我已经提到了我在代码中遇到错误的地方。

const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
    NSString *locationNo =NULL;
    NSString *querySQL = [NSString stringWithFormat:@"select count(*) from code"];
    const char *query_stmt = [querySQL UTF8String];

    if (sqlite3_prepare_v2(database,query_stmt, -1, &statement, NULL) == SQLITE_OK)
    {
        if (sqlite3_step(statement) == SQLITE_ROW)
        {
            locationNo = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
            int count= [locationNo intValue];
            sqlite3_close(database);
            NSLog(@"%@",locationNo);
            if(0==count)
            {
                NSString *insertSQL = [NSString stringWithFormat:@"insert into favourite_code (code_id,code_1,code_2,code_3,code_4,code_5,code_6, status, record_status) VALUES (\"%d\",\"%@\", \"%@\", \"%@\", \"%@\", \"%@\", \"%@\", \"%@\", \"%@\")",1 ,code1,code2,code3,code4,code5,code6,@"Y", @"Y"];

                const char *insert_stmt = [insertSQL UTF8String];
                sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL);
                if (sqlite3_step(statement) == SQLITE_DONE)
                {
                    return YES;
                }
                else {
                    return NO;
                }
                sqlite3_reset(statement);
                sqlite3_close(database);
            }
            else{


                =========================== Getting Error in the below lines =========================

                const char *sq1l = "update code SET code_1=?, code_2=?, code_3=?, code_4=?, code_5=?,code_6=? WHERE code_id=1";

                if (sqlite3_prepare_v2(database, sq1l, -1, &statement, NULL) != SQLITE_OK)
                {
                    NSLog(@"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
                }
                else
                {
                    sqlite3_bind_text(statement, 1, [code1 UTF8String], -1, SQLITE_TRANSIENT);
                    sqlite3_bind_text(statement, 2, [code1 UTF8String], -1, SQLITE_TRANSIENT);
                    sqlite3_bind_text(statement, 3, [code1 UTF8String], -1, SQLITE_TRANSIENT);
                    sqlite3_bind_text(statement, 4, [code1 UTF8String], -1, SQLITE_TRANSIENT);
                    sqlite3_bind_text(statement, 5, [code1 UTF8String], -1, SQLITE_TRANSIENT);
                    sqlite3_bind_text(statement, 6, [code1 UTF8String], -1, SQLITE_TRANSIENT);

                }

                int success = sqlite3_step(statement);
                if (success != SQLITE_DONE)
                {
                    NSLog(@"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
                    //result = FALSE;
                }
                else
                {
                    NSLog(@"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
                    //result = TRUE;
                }

                =================================END=========================================   


            }

            sqlite3_reset(statement);
        }
        else
        {
            NSLog(@"Not found");
            locationNo=@"1";
        }
        sqlite3_reset(statement);
    }
}

【问题讨论】:

    标签: ios sql sqlite


    【解决方案1】:

    一般来说,如果您有多个查询同时进行(或者您没有完成一些早期的 SQL 语句,或者您打开了多个线程,或者您已经多次打开数据库),您会得到这个。

    这段代码对sqlite3_closesqlite3_reset 的使用有点混乱(并且缺少sqlite3_finalize),这可能是问题的根源。

    An Introduction To The SQLite C/C++ Interface 中,他们指出了语句的正确顺序:

    • sqlite3_open(),打开数据库
    • sqlite3_prepare(),准备sql语句
    • sqlite3_bind(),将值绑定到 ?必要时的占位符
    • sqlite3_step(),执行 sql 和/或单步执行结果
    • sqlite3_column(),根据需要检索数据列
    • sqlite3_finalize(),完成/关闭准备好的sql语句
    • sqlite3_close(),关闭数据库

    底线,您的sqlite3_open 调用与末尾的单个sqlite3_close 语句不匹配(但您的代码中间有一个无关的sqlite3_close)。此外,每个sqlite3_prepare_v2 必须有自己的sqlite3_finalize(如果要重置准备好的语句,则只能使用sqlite3_reset,以便将其与新值绑定并再次单步执行;但您仍然需要sqlite3_finalize 时你已经完成了准备好的语句)。

    【讨论】:

    • 感谢您的回答。我试过你说的。我删除了 sql_close 并最终确定了我删除了 reset 也仍然遇到相同的错误。我做对了吗?如有错误请指正。
    • @2vision2 关闭数据库并用 finalize 替换重置是必要的步骤。但根本问题可能是您打开了两次数据库。例如,您的代码 sn-p 在开始时打开数据库,但在结束时不关闭它。如果你运行两次,你就会遇到问题。确保您匹配您的打开和关闭语句。确保每个sqlite3_open 都有一个sqlite3_close 并且每个sqlite3_prepare_v2 都有一个sqlite3_finalize 非常重要。
    • @2vision2 另外,您是否在这里执行任何多线程代码(例如 GCD、NSOperationQueue 或任何异步技术)?从多个线程/队列访问数据库时必须特别小心。
    • 是的,你是对的!对于每个打开,我都没有关闭现在它在将每个打开与关闭匹配后就可以工作了。感谢您的快速回复。
    • 我花了几个小时试图解决这个问题。但是我没有在循环中使用 finalize 。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    • 2020-06-14
    相关资源
    最近更新 更多