【发布时间】:2019-02-25 14:33:27
【问题描述】:
在调用sqlite3_step() 失败后,是否需要在准备好的语句上调用sqlite3_reset()?我正在使用 sqlite3 版本 3.23.1。我准备好的语句的生命周期如下:
- 在我的应用程序开始时,我全局执行
sqlite3_prepare_v2()并在应用程序的生命周期内保持准备好的语句的句柄可用。 - 当我准备好进行查询时,我调用
sqlite3_bind_*()函数之一,然后对该语句执行sqlite3_step(),直到返回SQLITE_ROW以外的其他内容。 - 然后执行下面的代码来重置语句。
这是我调用sqlite3_step() 后发生的部分代码。请注意,变量resultCode 保存最后一次调用sqlite3_step() 的返回值。
if (resultCode == SQLITE_DONE || resultCode == SQLITE_ROW)
{
if (sqlite3_reset(m_statement) != SQLITE_OK)
{
LogDbFailure(*m_db, "sqlite3_reset()");
}
}
else
{
LogDbFailure(*m_db, "sqlite3_step()");
success = false;
}
请注意,如果对 step 的调用失败,我不会进行重置。 Google 上的文档或搜索结果中没有任何内容表明必须在失败时调用 sqlite3_reset()。事实上,documentation 声明失败后调用sqlite3_reset() 也会失败:
如果最近对准备好的语句 S 的 sqlite3_step(S) 调用指示错误,则 sqlite3_reset(S) 返回适当的错误代码。
读到这里让我想到如果步骤失败我不应该调用重置函数。
谁能澄清一下?请注意,在我的情况下,sqlite3_step() 因SQLITE_BUSY 而失败。我正在使用 WAL 日志模式。一旦准备好的语句上的步骤失败,当我调用sqlite3_step() 时,该准备好的语句将永远处于忙碌状态。之后调用sqlite3_bind_*() 会返回sqlite3_bind_int64() failed (21): bad parameter or other API misuse(日志格式是我自己的,但21 是错误代码),这让我认为在失败情况下应该调用reset,因为所有错误似乎表示数据库正忙,因为准备好的语句由于缺少重置而卡在事务中间。
【问题讨论】: