ios - 合并两个 sqlite3 查询

标签 ios objective-c sqlite

我能否以某种方式组合这两个查询?

我在第二个查询中收到表未找到的错误,我认为它与第一个查询中的一些 sqlite 调用有关。

NSString *dayName = del.dayName;
int rowCount = del.tableRowNumber;

NSString *sqLiteDb = [[NSBundle mainBundle] pathForResource:@"banklist" ofType:@"sqlite3"];

if(sqlite3_open([sqLiteDb UTF8String], &_database) == SQLITE_OK)
{
    NSString *sqlStatement = [NSString stringWithFormat:@"UPDATE %@ SET recipe_name='%@' WHERE cell_id='%i'",dayName, info.name, rowCount];
    sqlite3_stmt *compiledStatement;

    if(sqlite3_prepare_v2(_database, [sqlStatement UTF8String] , -1, &compiledStatement, NULL) == SQLITE_OK)
    {
        sqlite3_bind_text( compiledStatement, 1, [sqLiteDb UTF8String], -1, SQLITE_TRANSIENT);
    }
    if(sqlite3_step(compiledStatement) != SQLITE_DONE )
    {
        NSLog( @"Save Error: %s", sqlite3_errmsg(_database) );
    }
    else
    {
        sqlite3_reset(compiledStatement);
    }

    sqlite3_finalize(compiledStatement);


    NSString *sqlStatement2 = [NSString stringWithFormat:@"UPDATE %@ SET recipe_id = (SELECT key FROM recipes WHERE name = Monday.recipe_name)",dayName];
    sqlite3_stmt *compiledStatement2;

    if(sqlite3_prepare_v2(_database, [sqlStatement2 UTF8String] , -1, &compiledStatement2, NULL) == SQLITE_OK)
    {
        sqlite3_bind_text( compiledStatement2, 1, [sqLiteDb UTF8String], -1, SQLITE_TRANSIENT);
    }
    if(sqlite3_step(compiledStatement2) != SQLITE_DONE )
    {
        NSLog( @"Save Error: %s", sqlite3_errmsg(_database) );
    }
    else
    {
        sqlite3_reset(compiledStatement2);
    }

    sqlite3_finalize(compiledStatement2);
}

sqlite3_close(_database);

谢谢

最佳答案

一些观察:

  1. 您可能不想使用 stringWithFormat 为您的查询提供参数。如果食谱是“Pat's Infamous Cookies”怎么办?该撇号将被解释为终止您的字符串,并且您的准备功能将失败。您应该在 SQL 中使用 ? 占位符并绑定(bind)值。参见 section 3 SQLite 文档。

  2. 虽然我建议您使用上面的 sqlite3_bind_text 函数,但您实际上是在调用 sqlite3_bind_text 并将数据库文件的路径传递给它。那个

    • 对于您的 SQL 没有意义,因为您没有任何 ? 占位符来绑定(bind)此值;和

    • 我完全不确定您为什么要将数据库路径传递给它。

    那个电话似乎不太可能奏效。如果您检查现有 sqlite_bind_text 调用的返回码,我敢打赌它不是 SQLITE_OK

  3. 如果您的 sqlite3_prepare_v2 调用失败(这是优化 SQL 时常见的失败点),您不会记录 sqlite3_errmsg .在 sqlite3_prepare_v2 失败后收到的 sqlite3_errmsg 是您将收到的最有用的错误消息之一(它会准确地告诉您 SQL 出了什么问题)。如果 sqlite3_prepare_v2 没有返回 SQLITE_OK,请务必检查 sqlite3_errmsg

因此可能会产生:

if(sqlite3_open([sqLiteDb UTF8String], &_database) == SQLITE_OK)
{
    NSString *sqlStatement = [NSString stringWithFormat:@"UPDATE %@ SET recipe_name=? WHERE cell_id=?",dayName];
    sqlite3_stmt *compiledStatement;

    if(sqlite3_prepare_v2(_database, [sqlStatement UTF8String] , -1, &compiledStatement, NULL) != SQLITE_OK)
    {
        NSLog(@"%s: prepare failed: %s", __FUNCTION__, sqlite3_errmsg(_database));
        sqlite3_close(_database);
        return;
    }

    if (sqlite3_bind_text( compiledStatement, 1, [info.name UTF8String], -1, SQLITE_TRANSIENT) != SQLITE_OK)
    {
        NSLog(@"%s: bind_text failed: %s", __FUNCTION__, sqlite3_errmsg(_database));
        sqlite3_finalize(compiledStatement);
        sqlite3_close(_database);
        return;
    }

    if (sqlite3_bind_int( compiledStatement, 2, rowCount) != SQLITE_OK)
    {
        NSLog(@"%s: bind_int failed: %s", __FUNCTION__, sqlite3_errmsg(_database));
        sqlite3_finalize(compiledStatement);
        sqlite3_close(_database);
        return;
    }

    if (sqlite3_step(compiledStatement) != SQLITE_DONE )
    {
        NSLog(@"Save Error: %s", sqlite3_errmsg(_database) );
        sqlite3_finalize(compiledStatement);
        sqlite3_close(_database);
        return;
    }

    // you don't need this unless you're going to reuse that prepared statement, which you aren't
    //
    //else
    //{
    //    sqlite3_reset(compiledStatement);
    //}

    sqlite3_finalize(compiledStatement);

    // did you really mean to hardcode "Monday" in this SQL?

    NSString *sqlStatement2 = [NSString stringWithFormat:@"UPDATE %@ SET recipe_id = (SELECT key FROM recipes WHERE name = Monday.recipe_name)",dayName];
    sqlite3_stmt *compiledStatement2;

    if(sqlite3_prepare_v2(_database, [sqlStatement2 UTF8String] , -1, &compiledStatement2, NULL) != SQLITE_OK)
    {
        NSLog(@"%s: prepare 2 failed: %s", __FUNCTION__, sqlite3_errmsg(_database));
        sqlite3_close(_database);
        return;
    }
    if(sqlite3_step(compiledStatement2) != SQLITE_DONE )
    {
        NSLog( @"Save 2 Error: %s", sqlite3_errmsg(_database) );
    }

    // again, not needed
    //
    //else
    //{
    //    sqlite3_reset(compiledStatement);
    //}

    sqlite3_finalize(compiledStatement2);
}

sqlite3_close(_database);

我必须承认,我对构建 SQL 并动态提供表名的数据模型并不着迷。我宁愿看到一个包含所有日期的表格,并将 dayName 作为该表格中的一列。但是你所拥有的应该可以工作,但这只是一个不寻常的结构。

关于ios - 合并两个 sqlite3 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18619612/

相关文章:

java - Objective-C相当于类方法中Java的匿名类

objective-c - 如何获取 Objective-C 类的 nil 属性的类名

ios - 向 iOS 中的 sqlite 数据库中插入一个可能为空的值

ios - 如何自定义分组表格 View 单元格的背景/边框颜色?

iphone - 应用程序只对肖像启用,但 UIImagePickerController 在 iOS6 中旋转

ios - 在添加到 subview 之前如何获取 UIView 的宽度和高度?

ios - 随机选择、不重复的Sql语句

iphone - iPhone的SQLite实现是否支持完整的SQLite 3标准?

ios - MPMusicPlayerController 在应用程序处于后台时播放音乐

ios - 如何在iOS中删除并重新安装应用程序来唯一标识设备?