我在插入一些数据后尝试从数据库中获取数据时出现问题。我无法从数据库中选择任何行。
数据库中有条目,但我无法获得任何结果。
我在AppDelegate :: application:didFinishWithOptions
中注释掉这一行[dbAccess importWithDelegate:result];
一切正常。但我无法找到解决这个问题的方法。 我希望你能帮助我。
DatabaseAccess级。
#import "KejithDatabaseAccess.h"
#import "KejithEntryQueryDelegate.h"
@interface KejithDatabaseAccess (){
sqlite3 *db;
NSString *writableDatabase;
sqlite3_stmt *statement;
}
@end
@implementation KejithDatabaseAccess
-(id)init
{
if((self = [super init]))
{
// initialize database and store in _db
}
return self;
}
-(void)initializeDatabase
{
[self createEditableDatabase];
// open the database connection
if(sqlite3_open([writableDatabase UTF8String], &db) == SQLITE_OK){
NSLog(@"Database: Connection was opened successfully");
} else {
// if something went wrong clean everything up
sqlite3_close(db);
NSAssert1(0, @"Database: Failed to open database connection. Error: '%s'", sqlite3_errmsg(db));
}
}
-(void)closeDatabase
{
if(sqlite3_close(db) != SQLITE_OK){
NSAssert1(0, @"Database: Failed to close database connection. Error: '%s'", sqlite3_errmsg(db));
}
}
-(void)createEditableDatabase
{
BOOL success;
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
// create writable database and store path for later use
writableDatabase = [documentsDir stringByAppendingPathComponent:@"main-rw.db"];
success = [fileManager fileExistsAtPath: writableDatabase];
// if writable database already exists return
if(success) return;
// the editable database does not exist
// copy the default DB to the application
// documents directory
NSString *defaultPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"main.db"];
success = [fileManager copyItemAtPath:defaultPath toPath:writableDatabase error:&error];
if(!success){
NSAssert1(0, @"Database: Failed to create writable database file: '%@'.", [error localizedDescription]);
}
}
-(NSMutableArray *)queryWithDelegate
{
[self initializeDatabase];
// do we have an delegate?
if(![self delegate])
return nil;
NSMutableArray *result = [[self delegate] query:db];
[self closeDatabase];
return result;
}
-(void)importWithDelegate:(NSMutableArray *)collection
{
[self initializeDatabase];
[[self delegate] import:collection into:db];
sqlite3_finalize(statement);
[self closeDatabase];
}
-(sqlite3 *)getWritableDatabase
{
return db;
}
@end
Database Delegate-Class
#import "KejithEntryQueryDelegate.h"
#import "KejithEntry.h"
@interface KejithEntryQueryDelegate ()
@property sqlite3 *database;
@end
@implementation KejithEntryQueryDelegate
@synthesize sql;
@synthesize statement;
-(id)init
{
if((self = [super init])){
[self initSQL];
}
return self;
}
-(void)initSQL
{
sql = "SELECT _id, entry_title, entry_description, entry_phone, entry_fax, entry_email, entry_website FROM entry";
}
-(NSMutableArray *)query:(sqlite3 *)database
{
// store database
[self setDatabase:database];
// initialize array to store found objects
NSMutableArray *entries = [[NSMutableArray alloc] init];
// prepare sql statement
int sqlResult = sqlite3_prepare_v2(database, sql, -1, &statement, NULL);
if(sqlResult == SQLITE_OK){
while(sqlite3_step(statement) == SQLITE_ROW){
// allocate object to store row
KejithEntry *entry = [[KejithEntry alloc] init];
// get data from columns
NSMutableString *title = [NSMutableString stringWithString:
[NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 1)]];
NSMutableString *description = [NSMutableString stringWithString:
[NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 2)]];
NSMutableString *phone = [NSMutableString stringWithString:
[NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 3)]];
NSMutableString *fax = [NSMutableString stringWithString:
[NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 4)]];
NSMutableString *email = [NSMutableString stringWithString:
[NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 5)]];
NSMutableString *website = [NSMutableString stringWithString:
[NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 5)]];
// set data in object
[entry setId:[NSNumber numberWithInt: sqlite3_column_int(statement, 0)]];
[entry setTitle:title];
[entry setDescription:description];
[entry setPhone:phone];
[entry setFax:fax];
[entry setEmail:email];
[entry setWebsite:website];
// put object into array
[entries addObject:entry];
}
// finalize the statement to release its resources
sqlite3_finalize(statement);
} else {
// log errors
NSLog(@"Database: Problem Occured in KejithEntryQueryDelegate.m");
NSLog(@"Database: Result Code: %d", sqlResult);
NSLog(@"Database: SQL-Error: %s", sqlite3_errmsg(database));
}
return entries;
}
-(void)import:(NSMutableArray *)collection into:(sqlite3 *)database
{
if([collection count] == 0)
return;
for(KejithEntry *entry in collection){
[self importEntry:entry into:database];
}
}
-(void)importEntry:(KejithEntry *)entry into:(sqlite3 *)database
{
sql = "INSERT INTO entry (entry_id, entry_title, entry_description, entry_phone, entry_fax, entry_email, entry_website, enty_latitude, entry_longitude, entry_category_id) \
VALUES \
(0,?,?,?,?,?,?,0,0,0);";
int sqlResult = sqlite3_prepare_v2(database, sql, -1, &statement, NULL);
sqlite3_bind_text(statement, 1, [[entry title] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 2, [[entry getDescription] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 3, [[entry phone] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 4, [[entry fax] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 5, [[entry email] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 6, [[entry website] UTF8String], -1, SQLITE_STATIC);
if(sqlite3_step(statement) != SQLITE_DONE){
NSLog(@">> Database: Failed to insert into Database");
NSLog(@"SQL Error Message: %s", sqlite3_errmsg(database));
}
sqlite3_finalize(statement);
}
@end
的AppDelegate ::应用:didFinishWithLaunchingOptions
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
// create delegate for entry xml parsing
id delegate = [[KejithEntryXmlDelegate alloc] init];
KejithXmlParser *parser = [[KejithXmlParser alloc] initWithUrl:[[NSURL alloc] initWithString:entryXmlUrl]];
KejithDatabaseAccess *dbAccess = [[KejithDatabaseAccess alloc] init];
KejithEntryQueryDelegate *dbEntryDelegate = [[KejithEntryQueryDelegate alloc] init];
// set delegate to parse xml file
[parser setDelegate:delegate];
// set delegate to query data to/from database
[dbAccess setDelegate:dbEntryDelegate];
// get results of xml parsing
NSMutableArray *result = [parser parse];
NSLog(@"Count of ParseResult: %d", [result count]);
[dbAccess importWithDelegate:result];
NSLog(@"Count of DatabaseResult: %d", [[dbAccess queryWithDelegate] count]);
return YES;
}
没有[dbAccess importWithDelegate:result]的控制台输出已注释掉:
2013-12-08 15:59:44.035 staedteApp[30202:70b] Database: Connection was opened successfully
2013-12-08 15:59:44.048 staedteApp[30202:70b] Database: Connection was opened successfully
2013-12-08 15:59:44.049 staedteApp[30202:70b] Count of DatabaseResult: 0
使用[dbAccess importWithDelegate:result]注释掉的控制台输出:
2013-12-08 16:17:18.084 staedteApp[30267:70b] Database: Connection was opened successfully
2013-12-08 16:17:18.091 staedteApp[30267:70b] Count of DatabaseResult: 50
编辑#1 ----- 更新了KejithEntryQueryDelegate :: importEntry:into
-(void)importEntry:(KejithEntry *)entry into:(sqlite3 *)database
{
sql = "INSERT INTO entry (entry_id, entry_title, entry_description, entry_phone, entry_fax, entry_email, entry_website, enty_latitude, entry_longitude, entry_category_id) \
VALUES \
(0,?,?,?,?,?,?,0,0,0);";
int sqlResult = sqlite3_prepare_v2(database, sql, -1, &statement, NULL);
if(sqlResult != SQLITE_DONE){
sqlite3_bind_text(statement, 1, [[entry title] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 2, [[entry getDescription] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 3, [[entry phone] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 4, [[entry fax] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 5, [[entry email] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 6, [[entry website] UTF8String], -1, SQLITE_STATIC);
int sqlStepResult;
if((sqlStepResult = sqlite3_step(statement)) != SQLITE_DONE){
NSLog(@">> Database: Failed to insert into Database");
NSLog(@"SQL Error Message: %s", sqlite3_errmsg(database));
NSLog(@"SQL Step Result: %d", sqlStepResult);
}
} else {
NSLog(@"Database: Problem Occured in KejithEntryQueryDelegate.m step");
NSLog(@"Database: Result Code: %d", sqlResult);
NSLog(@"Database: SQL-Error: %s", sqlite3_errmsg(database));
}
sqlite3_finalize(statement);
}
答案 0 :(得分:0)
问题是您正在为sql
使用实例变量,在创建SELECT
时将其设置为KejithEntryQueryDelegate
语句,并将其更改为INSERT
语句在importEntry:into:
方法中,但是当您调用query:
时,即使代码明确假定它应该是SELECT
语句,sql
仍然是INSERT
语句。
通过查看sqlite3_step
的结果代码(下面的第3点),可以快速识别问题。从sqlResult != DONE
开始,您想要记录问题并报告“entry.entry_title可能不是NULL”(这在SELECT
语句中没有意义,这让我意识到旧的INSERT
1}}语句仍然在sql
变量中。
我的原始答案,基于对代码的一瞥,如下所示。第3点是重要的观察结果。
只是查看代码,我看不到任何明显会导致您描述的行为的内容。如果我正确地关注了您,您说如果您不导入数据,则会找到50条记录,但如果您执行尝试导入数据,那么不仅仅是您没有看到新数据,但突然发现没有任何内容(包括已经存在的记录)。那真的是你说的吗?那是好奇的行为。事实上,如果这是问题,那将导致我怀疑导入的尝试导致后续尝试读取失败。
这里唯一明显的SQLite问题是importWithDelegate
不应该调用sqlite3_finalize
。我甚至不知道为什么KejithDatabaseAccess
有一个sqlite3_stmt
,因为你没有在那个班级准备任何陈述。也许使用一些无效的sqlite3_finalize
来调用sqlite3_stmt
会导致问题?
这里有一些小问题:
importEntry:into:
应该检查sqlite3_prepare_v2
语句的结果。在其他地方,您确认准备工作在继续之前成功,但不在此处。
query
方法将电子邮件地址存储到网站媒体资源中。
我还会在sqlite3_step
方法中保存query
的结果,以便您可以检查错误,例如:
while((sqlResult = sqlite3_step(statement)) == SQLITE_ROW) {
// do all of your updating of entries here
}
if (sqlResult != SQLITE_DONE) {
NSLog(@"Database: Problem Occured in KejithEntryQueryDelegate.m step");
NSLog(@"Database: Result Code: %d", sqlResult);
NSLog(@"Database: SQL-Error: %s", sqlite3_errmsg(database));
}
目前,如果您的sqlite3_step
方法失败,您将永远不会知道。