如何完成所有挂起的SELECT语句?

时间:2016-04-14 15:58:15

标签: c sqlite

SQLite wiki page for "database is locked"说:

  

有时人们认为他们已完成SELECT语句,因为sqlite3_step()已返回SQLITE_DONE。但在调用SELECTsqlite3_reset()之前,sqlite3_finalize()并不完整。   截至登记[3902](版本3.3.17之后的2007-05-02),现在允许CREATE声明。

我当然可以关闭并重新打开数据库,但这会使所有准备好的语句无效。是否存在其他方式不会让我跟踪所有待处理的SELECT语句?

1 个答案:

答案 0 :(得分:1)

  

我当然可以关闭并重新打开数据库,但这会使所有准备好的语句无效。是否存在另一种不涉及跟踪所有挂起的SELECT语句的方法?

SQLite已经跟踪了所有准备好的语句,它提供了sqlite3_next_stmt()作为一种机制,您可以通过该机制遍历其列表。还有sqlite3_stmt_busy(),您可以通过它来测试一个语句是否持有一个事务处于打开状态,但是这不会帮助您识别已经运行完成的语句,因此它们与实时事务无关,但仍然具有由于尚未最终确定或重置而分配给它们的数据库资源。

这是一种可以重置SQLite当前已知的所有预准备语句的方法:

    sqlite3 *db = /* ... */
    sqlite3_stmt *stmt;

    /* ensure that there is no open transaction; will fail harmlessly if
       there already is none */
    sqlite3_exec(db, "rollback", NULL, NULL, NULL);

    /* Clean up any outstanding prepared statements */
    for (stmt = sqlite3_next_stmt(db, NULL); stmt; stmt = sqlite3_next_stmt(db, stmt)) {
        int result = sqlite3_reset(stmt);
        /* handle errors ... */
    }

重置不需要它的语句应该没有害处。

话虽如此,您应该跟踪当前正在运行的语句,并确保在完成他们正在服务的当前结果集时重置它们。这需要一点纪律,但这是正确的做法。