无法从 IOS 中的 sqlite 获取值

Posted

技术标签:

【中文标题】无法从 IOS 中的 sqlite 获取值【英文标题】:cannot fetch value from sqlite in IOS 【发布时间】:2015-04-22 12:24:26 【问题描述】:

表值:

ID=1 CUSTOMERID=1 NAME=John EMAIL=email USERNAME=usernaeme

我正在使用此代码通过此代码从 Usertable 中获取 customerId

@try 
    //CustomerIdField=@"admin";
   // customerUsername=@"admin";
    NSLog(@"the value of customerusername is %@",customerUsername);
    NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    NSString *docsDir = [dirPaths objectAtIndex:0];
NSLog(@"inside function");
databasePath  = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: @"EBook.db" ]];
    const char *dbpath;
    @try 
        dbpath = [databasePath UTF8String];
        NSLog(@"the  const char is %s",dbpath);
    
    @catch (NSException *exception) 
        NSLog(@"the exception3 is %@",exception);
    


    if (sqlite3_open(dbpath, &Ebookreaderdb) == SQLITE_OK)

    
    NSString *selectSQL = [NSString stringWithFormat: @"SELECT CUSTOMERID FROM Usertable WHERE EMAIL=\"%@\"",customerUsername];


        sqlite3_stmt  *selstatement;
    const char *select_stmt = [selectSQL UTF8String];
    //NSMutableArray *resultArray = [[NSMutableArray alloc]init];
    if (sqlite3_prepare_v2(Ebookreaderdb,
                           select_stmt, -1, &selstatement, NULL ) == SQLITE_OK)
    

        NSLog(@"inside sqlite OK"); //this prints in log
        if (sqlite3_step(selstatement) == SQLITE_ROW)
        

            NSLog(@"inside sqlite ROW"); // this is also printing in log
            NSString *userInfoStr = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selstatement,1)];
            NSLog(@"val is %@",userInfoStr);
          char *tmp = sqlite3_column_text(selstatement,1);
            if (tmp == NULL)
                CustomerIdField = nil;
            else
                CustomerIdField = [[NSString alloc] initWithUTF8String:tmp];



             CustomerIdField = [[NSString alloc] initWithUTF8String:
                             (const char *) sqlite3_column_text(selstatement,1)];



            NSLog(@"inside customer is %@",CustomerIdField);
           // [resultArray addObject:name];

        

        else
            NSLog(@"Not found");
          //  return nil;
        
        sqlite3_reset(selstatement);
    

但我得到了这个异常Newpjtonfriday[2165:84017] the exception is 2 *** +[NSString stringWithUTF8String:]: NULL cString

我用谷歌搜索了上面的结果,到处都说该值为 null,这就是发生异常的原因。但在我的情况下,价值就在那里。

因为代码 NSLog(@"内部 sqlite ROW");

进入日志意味着表中存在一行。但无法获取它。

请帮忙

【问题讨论】:

顺便说一句,不要使用stringWithFormat 来构建SQL 语句。使用? 占位符和sqlite3_bind_text 函数(令人困惑的是,它使用从一开始的索引,与sqlite3_column_text 的从零开始的索引不同)。 您调用了sqlite3_reset(用于将绑定列重置为准备好的语句,因此可以再次执行该语句)并且您显然打算调用sqlite3_finalize(释放内存)。将reset 替换为finalize。另外,您的意思是在此处打开数据库而不是关闭它吗?就个人而言,我会将数据库的打开与 SQL 语句的执行分开,但可以做任何你想做的事情,但只要确保每个打开都有其相应的关闭调用。不用说,这些烦人的小细节让像 FMDB 这样的库如此引人注目...... 【参考方案1】:

我认为这是一个错字:

@"SELECT CUSTOMERID FROM Usertable WHERE EMAIL=\"%@\"",customerUsername;

您传递的是用户名而不是电子邮件?或者你的意思是SELECT ... WHERE USERNAME=

此外,也不需要任何 @try/@catch 块,因为我看不到该代码如何引发 Objective-C 异常。

最后一件事;为了避免 SQL 注入攻击,您应该将值绑定到您的语句中,而不是像您在此处所做的那样将它们格式化为字符串。

【讨论】:

【参考方案2】:

小建议如果您刚开始在 ios 上进行开发,请尝试使用一些库 (FMDB to easy work with SQLite) 以使某些任务更直接。

回答您的问题 如果表中有任何行,请尝试“SELECT * FROM Usertable”。 其次,您应该检查行中的值是否不为 NULL。 要获得简单的解决方案,请使用 Datum SQLite Free(Mac os X) 之类的东西,或者您可以使用 SELECT COUNT 来确保表中有任何行。 尝试您的选择,如果应用程序返回行但您的列中没有值,这意味着您在写入数据库逻辑时遇到问题但在读取逻辑中没有问题,并且您正在尝试获取在您想要的列上具有空值的行。那就是为什么这种方法不起作用:

[NSString stringWithUTF8String:]: NULL cString

它抛出了一个异常,因为你没有字符串并试图将 NULL 发送到方法。

【讨论】:

【参考方案3】:

sqlite3_column_text 索引号是从零开始的,而不是从一开始的。因此,这一行:

char *tmp = sqlite3_column_text(selstatement, 1);

应该是:

char *tmp = sqlite3_column_text(selstatement, 0);

顺便说一句,您对这个tmp 变量的处理是在使用它之前检查以确保它不是NULL 的一种谨慎方式。不幸的是,在同一例程的其他地方,您直接使用 sqlite3_column_text 值(这就是您的应用程序崩溃的原因,而不是优雅地报告错误)。您在此处对sqlite3_column_text 进行了多次冗余调用。我建议使用您在此 tmp 变量中使用的模式。

【讨论】:

【参考方案4】:

让我给你我的建议,我尝试了你刚才所做的,我也得到了错误。然后我做了一些谷歌搜索,找到了这个链接

http://www.raywenderlich.com/913/sqlite-tutorial-for-ios-making-our-app

只需修改这些代码

 char *tmp = sqlite3_column_text(selstatement,1);
        if (tmp == NULL)
            CustomerIdField = nil;
        else
            CustomerIdField = [[NSString alloc] initWithUTF8String:tmp];



         CustomerIdField = [[NSString alloc] initWithUTF8String:
                         (const char *) sqlite3_column_text(selstatement,1)];



        NSLog(@"inside customer is %@",CustomerIdField);

int tmp = sqlite3_column_int(selstatement,0);// my case it is int
char *nameChars = (char *) sqlite3_column_text(selstatement, 1);// here is the change occuring please refer this
NSString *name = [[NSString alloc] initWithUTF8String:nameChars]; //  there are two steps first fetch as char, then change to String
 NSLog(@"customerid is %d",tmp);
  NSLog(@"customer name is %@",name);

试试这个,它对我有用..

我认为问题在于您直接将 coustomerId 作为字符串获取

在你的情况下,试试这个

char *custId = (char *) sqlite3_column_text(selstatement, 0);
NSString *customerId = [[NSString alloc] initWithUTF8String:custId];

:-)

【讨论】:

以上是关于无法从 IOS 中的 sqlite 获取值的主要内容,如果未能解决你的问题,请参考以下文章