1

我可以将这两个查询结合起来吗?

我在第二个查询中找不到表的错误,我认为这与第一个查询中的一些 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);

谢谢

4

2 回答 2

1

也许您在这部分语句中有错误:

SELECT key
FROM recipes
WHERE name = Monday.recipe_name
于 2013-09-04T17:07:49.753 回答
1

几点观察:

  1. 您可能不想使用stringWithFormat. 如果食谱是“Pat 臭名昭著的饼干”怎么办?该撇号将被解释为终止您的字符串,并且您的准备功能将失败。您应该?在 SQL 中使用占位符并绑定值。请参阅SQLite 文档的第 3 节。

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

    • 考虑到您的 SQL,这没有意义,因为您没有任何?占位符可以将此值绑定到;和

    • 我不知道你为什么要把数据库的路径传递给它。

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

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

因此,这可能会产生:

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在该表中创建一列。但是您所拥有的应该可以工作,但这只是一个不寻常的构造。

于 2013-09-04T17:31:52.153 回答