无法从 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 获取值的主要内容,如果未能解决你的问题,请参考以下文章

无法从 VS2019 中的 Boost 属性树映射值中获取值()

无法从片段中的 SQLite 获取数据

如何获取存储在 iOS 持久性 sqlite 数据库中的值?

如何从 QMultiMap 中的值中获取键?

如何从 Javascript 中的 SQLite 数据库中获取表数据?

无法从 iOS 应用程序打开 sqlite DB