ios - sqlite3_step 在将数据插入 sqlite 时返回错误代码 5
<p><p>我有一个使用 sqlite 的应用程序,我正在检查表中是否存在特定记录。如果没有,我将数据插入表中,但插入时出现错误代码 5。</p>
<p>这是我的代码</p>
<pre><code>-(int)addPayOptions:(NSString*)owner:(NSString*)bank:(NSString*)number:(NSString*)scheme:(NSString*)type:(NSString*)expiryDate:(NSString*)name
{
NSString *queryString=nil;
NSString *dbPath = ;
int val =0;
@try {
queryString=;
if (sqlite3_open(, &database)==SQLITE_OK)
{
int resp_code =sqlite3_prepare_v2(database, , -1, &statement, NULL);
NSLog(@"%d",resp_code);
if (sqlite3_prepare_v2(database, , -1, &statement, NULL)==SQLITE_OK)
{
if (sqlite3_step(statement)==SQLITE_ROW)
{
val=0;
return val;
sqlite3_reset(statement);
}
else
{
BOOL checkinserted =;
if (checkinserted)
{
val=1;
return val;
}
else
{
val=0;
return val;
}
}
sqlite3_finalize(statement);
}
}
sqlite3_close(database);
}
@catch (NSException *exception) {
}
return val;
}
-(BOOL)insertPayOptions:(NSString*)owner:(NSString*)bank:(NSString*)number:(NSString*)defaultOption:(NSString*)scheme:(NSString*)type:(NSString*)expiryDate:(NSString*)name
{
const char *dbpath = ;
BOOL check = '\0';
if (sqlite3_open(, &database)==SQLITE_OK)
{
NSString *insertSQL = ;
if(sqlite3_prepare_v2(database, , -1, &statement, NULL)==SQLITE_OK)
{
NSLog(@"%d",sqlite3_step(statement));
if (sqlite3_step(statement)==SQLITE_DONE)
{
check=YES;
}
else
{
check =NO;
}
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
return check;
}
</code></pre></p>
<br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
<p><p>值 5 是 <code>SQLITE_BUSY</code>,这意味着数据库当前正忙于做其他事情(例如,之前的 SQLite 调用没有正确完成和关闭)。 </p>
<p>也许巧合的是,这种方法恰好是导致此 <code>SQLITE_BUSY</code> 错误的那种编程错误的完美示例。在您的代码中,如果 <code>sqlite3_prepare_v2</code> 语句成功,您将永远无法访问您的 <code>sqlite3_finalize</code> 或 <code>sqlite3_close</code> 语句,因为您 <code>return</code> 在进行那些敲定/关闭电话之前。因此,下次调用此方法时,它会告诉您数据库正忙(因为之前的调用从未完成并关闭)。</p>
<p>在执行 SQLite 调用的方法中调用 <code>return</code> 时要非常非常小心,或者如果确实在方法中使用了 <code>return</code>,请确保调用适当的<code>sqlite3_finalize</code> 和 <code>sqlite3_close</code> 调用 <em>before</em> 返回。或者,更好的是,重构您的代码,以尽量减少散布在整个方法中的这些 <code>return</code> 语句,这样就更难犯这个错误了。</p>
<p>顺便说一下,虽然这种方法很方便地说明了会导致 <code>SQLITE_BUSY</code> 的那种编程错误,但这并不一定是代码中唯一无法完成语句的情况或无法关闭数据库。您确实应该检查所有与 SQLite 相关的函数并考虑每个执行路径,并确保不可能调用 <code>sqlite3_finalize</code> 和 <code>sqlite3_close</code> 失败。 </p>
<p>一些不相关的观察:</p>
<ol>
<li><p>顺便说一句,如果数据库调用失败,记录 <code>sqlite3_errmsg</code> 通常很有用,这将提供更多关于错误确切性质的信息。例如,现在,如果 prepare 语句失败,您将默默返回,而没有任何有关任何潜在错误的有用诊断信息。</p></li>
<li><p>你应该避免在 Objective-C 中使用 <code>try</code>/<code>catch</code>block 。虽然这在其他编程语言中是一个重要的构造,但在 Objective-C 中,您应该通过查看返回码(以及在提供的地方检查 <code>NSError</code> 对象)来完成所有错误处理。事实上,由于你的 <code>catch</code>block 什么都不做,你实际上会掩盖任何发生的异常,所以情况更糟。</p></li>
<li><p>你应该非常小心使用 <code>stringWithFormat</code> 来构建你的 SQL 语句。如果该值包含撇号,您的 SQL 将失败。请改用 <code>sqlite3_bind_text</code>,与使用 <code>?</code> 占位符的 SQL 结合使用。</p></li>
<li><p>在这种情况下,不需要使用 <code>sqlite3_reset</code> 语句。只有在重用之前准备好的 <code>sqlite3_stmt</code> 时才使用 <code>sqlite3_reset</code>,而这里没有这样做。您在 <code>return</code> 语句之后调用了 <code>sqlite3_reset</code>,所以这可能是学术性的,但尽管如此,可以删除此 <code>sqlite3_reset</code> 调用。</p></li>
</ol></p>
<p style="font-size: 20px;">关于ios - sqlite3_step 在将数据插入 sqlite 时返回错误代码 5,我们在Stack Overflow上找到一个类似的问题:
<a href="https://stackoverflow.com/questions/22960923/" rel="noreferrer noopener nofollow" style="color: red;">
https://stackoverflow.com/questions/22960923/
</a>
</p>
页:
[1]