gpt4 book ai didi

objective-c - 将项目添加到 sqlite3 数据库不起作用

转载 作者:行者123 更新时间:2023-12-03 19:46:32 26 4
gpt4 key购买 nike

我有以下代码,它是根据 youtube 上的教程实现的,但是我更改了其中一些以满足我的目的,即插入硬编码的项目.. 创建了数据库和表,但我发现 addItems 不是添加。
我不认为 addItemToTable 方法有问题,
我认为这是此处列出的第一部分的逻辑错误,但找不到它。任何帮助都会很棒

提前致谢

这些是项目:

    table_ok = YES;
if (table_ok) {
if (!db_open_status) {
[self openDBWithSQLName:dataBaseName];
NSLog(@"DB opened");
}

NSMutableDictionary *objectColsVals = [[NSMutableDictionary alloc]init];
NSString *this_id = @"12";
NSString *this_name = @"and";
NSString *this_email = @"123@hotmail.com";
NSString *this_password = @"aa11111";
NSString *this_role = @"Marketing";
[objectColsVals setValue:this_id forKey:[my_columns_names objectAtIndex:0]];
[objectColsVals setValue:this_name forKey:[my_columns_names objectAtIndex:1]];
[objectColsVals setValue:this_email forKey:[my_columns_names objectAtIndex:2]];
[objectColsVals setValue:this_password forKey:[my_columns_names objectAtIndex:3]];
[objectColsVals setValue:this_role forKey:[my_columns_names objectAtIndex:4]];

if ([[objectColsVals allKeys] count] > 0) {
if ([self addItemToTable:tableName WithColumnValues:objectColsVals]) {
NSLog(@"inserted");
[self closeDB];
}
}

这个方法:
-(BOOL)addItemToTable:(NSString *)usetable WithColumnValues:(NSDictionary *)valueObject{
BOOL has_beenAdded = NO;
NSString *mycolumns = @"";
NSString *myvalues = @"";
//loop through all the value keys
for (int r=0; r<[[valueObject allKeys] count]; r++) {
NSString *this_keyname = [[valueObject allKeys]objectAtIndex:r];
mycolumns = [mycolumns stringByAppendingString:this_keyname];
NSString *thisval = [NSString stringWithFormat:@"'%@'",[valueObject objectForKey:this_keyname]];
myvalues = [myvalues stringByAppendingString:thisval];
//add commas to seperate the col and val lists before last item
if (r<(([[valueObject allKeys] count])-1)) {
mycolumns = [mycolumns stringByAppendingString:@","];
myvalues = [myvalues stringByAppendingString:@","];
}
}

NSString *myinsert = [NSString stringWithFormat:@"INSERT INTO %@ (%@) VALUES(%@)",usetable,mycolumns,myvalues];
char *err;
if (sqlite3_exec(estate_db, [myinsert UTF8String], NULL, NULL, &err) != SQLITE_OK) {
sqlite3_close(estate_db);
}else{
has_beenAdded = YES;
}

return has_beenAdded;
}

最佳答案

就你在这里得到的东西而言,很难说问题出在哪里。似乎没有什么明显的错误。至少,一个人应该:

  • 检查结果INSERT您以编程方式构建的语句,以确保没有一些微妙的问题无法对代码进行粗略检查;
  • 如果有的话sqlite3_xxx()调用失败(特别是如果 sqlite3_exec 返回除 SQLITE_OK 之外的任何内容),然后记录错误消息(err 变量,或通过调用 sqlite3_errmsg() );如果您不查看这些错误消息,您只是在盲目飞行;和
  • 在模拟器上运行应用程序,然后在您的 Mac 上打开模拟器的数据库副本(在 ~/Library/Application Support/iPhone Simulator 目录中;如果 ~/Library 文件夹被隐藏,请通过在终端命令行中运行 chflags -nohidden ~/Library 命令来取消隐藏它工具)并直接检查数据库的内容。验证列名、表名等

  • 同样,目前还不清楚问题出在哪里,但它可能在于一些简单的事情,比如在打开数据库或创建有问题的表时出现一些困惑。在我们确认错误消息和实际 SQL 之前,很难说。从尝试打开捆绑中数据库的只读副本到错误调用 sqlite3_open 都可能是这样。并在不知不觉中创建了一个新的空白数据库。您确实应该更新问题并共享创建数据库的代码(或从包中复制它),以及执行上面概述的一些诊断步骤。

    话虽如此,我真的不鼓励您使用 stringWithFormat 将值添加到 SQL 中。 . SQL的动态构建很好,但你真的不应该使用 stringWithFormat将值插入 SQL 本身。鉴于您使用单引号引用文本值,如果此人的姓氏是 O'Brian 怎么办? ?或者,如果您将例程更改为使用双引号,那么如果此人的姓名是 Dwayne "The Rock" Johnson,该怎么办? ?如果字符串分隔符出现在数据值中,则当前代码可能会失败。更糟糕的是,您在技术上将自己暴露在 SQL 注入(inject)攻击之下。

    您通常应该做的是使用 ?占位符。例如,考虑一个定义如下的字典:
    NSDictionary *dataToInsert = @{@"name"        : @"Jack",
    @"id" : @37,
    @"password" : @"feefifofum",
    @"role" : [NSNull null],
    @"email" : @"jack@magicbeans.fairyland.com",
    @"hourly_wage" : @12.85};

    您要做的是构建如下所示的 SQL 语句:
    INSERT INTO test (name,id,password,role,email,hourly_wage) VALUES (?,?,?,?,?,?)

    然后你想将这些值绑定(bind)到那些 ?使用 sqlite3_bind_xxx() 的占位符职能。

    因此,您可以像这样创建和准备该 SQL 语句(构建 values 的数组和 placeholders 的数组):
    NSArray *keys = [dataToInsert allKeys];
    NSMutableArray *values = [NSMutableArray arrayWithCapacity:[keys count]];
    NSMutableArray *placeholders = [NSMutableArray arrayWithCapacity:[keys count]];

    // build array of values and array of question mark placeholders

    for (NSString *key in keys) {
    [values addObject:[dataToInsert objectForKey:key]];
    [placeholders addObject:@"?"];
    }

    // use the `keys` and `placeholders` arrays to build the SQL

    NSString *insertSql = [NSString stringWithFormat:@"INSERT INTO %@ (%@) VALUES (%@)",
    tableName,
    [keys componentsJoinedByString:@","],
    [placeholders componentsJoinedByString:@","]];

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

    // statement is prepared, but we still have to bind the values...

    然后,您可以使用以下内容绑定(bind)这些值。这是对 values 中对象的类进行动态检查。数组(如果是 NSNumber ,请查看 objCType 以确定数字的类型):
    // now use the `values` array to bind values to the ? placeholders

    [values enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    int rc = SQLITE_ERROR;

    if ([obj isKindOfClass:[NSString class]])
    rc = sqlite3_bind_text(statement, idx + 1, [obj UTF8String], -1, SQLITE_TRANSIENT);
    else if ([obj isKindOfClass:[NSNull class]])
    rc = sqlite3_bind_null(statement, idx + 1);
    else if ([obj isKindOfClass:[NSNumber class]]) {
    const char *objCType = [obj objCType];

    if (strcmp(objCType, @encode(int)) == 0 || strcmp(objCType, @encode(unsigned int)) == 0 || strcmp(objCType, @encode(short)) == 0 || strcmp(objCType, @encode(unsigned short)) == 0 || strcmp(objCType, @encode(char)) == 0 || strcmp(objCType, @encode(unsigned char)) == 0)
    rc = sqlite3_bind_int(statement, idx + 1, [obj integerValue]);
    else if (strcmp(objCType, @encode(long)) == 0 || strcmp(objCType, @encode(unsigned long)) == 0 || strcmp(objCType, @encode(long long)) == 0 || strcmp(objCType, @encode(unsigned long long)) == 0)
    rc = sqlite3_bind_int64(statement, idx + 1, [obj longLongValue]);
    else if (strcmp(objCType, @encode(float)) == 0 || strcmp(objCType, @encode(double)) == 0)
    rc = sqlite3_bind_double(statement, idx + 1, [obj doubleValue]);
    else {
    NSLog(@"column %d is %@ but has unknown numeric type %s; will use `description`", idx + 1, obj, objCType);
    rc = sqlite3_bind_text(statement, idx + 1, [[obj description] UTF8String], -1, SQLITE_TRANSIENT);
    }
    }
    else
    rc = sqlite3_bind_text(statement, idx + 1, [[obj description] UTF8String], -1, SQLITE_TRANSIENT);

    if (rc != SQLITE_OK)
    {
    NSLog(@"bind %d failed: %s", idx + 1, sqlite3_errmsg(db));
    sqlite3_finalize(statement);
    sqlite3_close(db);
    return;
    }
    }];

    if (sqlite3_step(statement) != SQLITE_DONE) {
    NSLog(@"step failed: %s", sqlite3_errmsg(db));
    sqlite3_close(db);
    return;
    }

    sqlite3_finalize(statement);

    关于objective-c - 将项目添加到 sqlite3 数据库不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20873904/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com