Ios 在SQLite语句中使用NSString/参数

Ios 在SQLite语句中使用NSString/参数,ios,objective-c,sqlite,Ios,Objective C,Sqlite,我的代码在下面。我的值\u emailVaue\u passwordValue和\u nameValue取自我应用程序中的UITextFields。我的印象是,将这些值传递到SQLite代码中的参数将允许我在这些值中使用特殊字符,例如双引号(“),但是,如果我将它们放进去,SQLite将崩溃。我是否做错了什么 我知道最好使用类似FMDB的东西,但我希望有一个更快的修复程序让我通过即将到来的演示 谢谢你的帮助,谢谢 if (sqlite3_open(dbpath, &_contactDB)

我的代码在下面。我的值
\u emailVaue
\u passwordValue和
\u nameValue
取自我应用程序中的
UITextFields
。我的印象是,将这些值传递到SQLite代码中的参数将允许我在这些值中使用特殊字符,例如双引号(“),但是,如果我将它们放进去,SQLite将崩溃。我是否做错了什么

我知道最好使用类似FMDB的东西,但我希望有一个更快的修复程序让我通过即将到来的演示

谢谢你的帮助,谢谢

if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK)
{

    NSString *insertSQL = [NSString stringWithFormat:
                           @"INSERT INTO CONTACTS (email, password, name) VALUES (\"%@\", \"%@\", \"%@\")",
                           _emailValue, _passwordValue, _nameValue];
    NSLog(insertSQL);
    const char *insert_stmt = [insertSQL UTF8String];
    sqlite3_prepare_v2(_contactDB, insert_stmt,
                       -1, &statement, NULL);
    if (sqlite3_step(statement) == SQLITE_DONE)
    {

    } else {

    }
    sqlite3_finalize(statement);
    sqlite3_close(_contactDB);
}

我希望它可以回答我自己的问题,如果它似乎工作。希望有人会发现它有用。将感谢任何反馈,我可能会出错

sqlite3_stmt    *statement;
const char *dbpath = [_databasePath UTF8String];
const char *insertSQL;
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK)
{
    insertSQL = "INSERT INTO CONTACTS (email, password, name) VALUES (?, ?, ?)";
    if(sqlite3_prepare_v2(_contactDB, insertSQL, -1, &statement, NULL) == SQLITE_OK)
    {
    sqlite3_bind_text(statement, 1, [_emailValue UTF8String], -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(statement, 2, [_passwordValue UTF8String], -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(statement, 3, [_nameValue UTF8String], -1, SQLITE_TRANSIENT);
    }
    if (sqlite3_step(statement) == SQLITE_DONE)
    {
//worked
    } else {


//didn't work
    }
    sqlite3_finalize(statement);
    sqlite3_close(_contactDB);
}

我将尝试解释您的代码发生了什么,以及如何改进代码以避免崩溃发生。我完全同意使用绑定参数,此答案仅作为如何修复崩溃的答案发布,可能会帮助没有时间切换到绑定语句的人

发生的事情如下:

  • sqlite3\u prepare\u v2()
    失败,因为您的查询字符串无效,因为您的字符串包含
    字符
  • 由于上述原因,
    语句
    要么为
    NULL
    ,要么包含垃圾值
  • sqlite3\u step()
    由于无效指针作为参数传递而崩溃
  • 以下是修复方法:

  • 通过将
    \“
    替换为
    \”
    来转义所有字符串,这将生成有效的查询;如果在查询中使用了
    '
    ,则必须将
    '
    替换为
    \'
  • 电子邮件示例:

    NSString *escapedEmail = [_emailValue stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];
    
  • 即使您确信查询是正确的,在任何其他
    sqlite
    调用中使用该语句之前,仍然必须检查
    sqlite3\u prepare\u v2()
    的结果

  • 一般来说,在处理C API时,您需要非常谨慎地编写代码,因为如果您忘记检查
    NULL
    指针,C不会原谅您。Objective-C更软,因为它允许您向
    nil
    对象发送消息。

    切勿使用
    stringWithFormat:
    构建查询。使用适当的
    sqlite3\u Bind\u xxx
    函数正确绑定值。请参阅,我建议使用FMDB作为在Objective-C中使用SQLite的最快和最简单的方法。@maddy感谢链接,我现在可以使用它了,我将发布answer@PaulDardeau谢谢你的提示,保罗,在我即将进行的演示之后,可能会转移到FMDB,只是很难估计它的难度。请注意,只有在
    sqlite3\u prepare\u v2()
    成功的情况下,才应该执行
    sqlite3\u step()
    sqlite3\u finalize()
    ,否则,如果出于某种原因,
    sqlite
    无法准备语句(例如,如果某些内存分配失败),您将再次遇到崩溃。