如何从我的 sqlite 数据库中获取数据

Posted

技术标签:

【中文标题】如何从我的 sqlite 数据库中获取数据【英文标题】:how to fetch data from my sqlite database 【发布时间】:2013-10-06 05:29:40 【问题描述】:

我是 iphone 开发者的初学者。我已经创建了 sqlite 数据库。我制作了学生数据表,我想显示来自 sqlite 数据库的数据,我使用从下面的代码中获取数据,但是有一些错误,我无法从我在下面的代码中使用的数据库中获取数据..

#import <Foundation/Foundation.h>
// This includes the header for the SQLite library.
#import <sqlite3.h>

@interface DBConnection : NSObject 

    //reference to the SQLite database.
@private
    sqlite3 *g_database;


@property (nonatomic,assign,readonly) sqlite3 *database;

+ (DBConnection *) sharedConnection;
+ (BOOL) executeQuery:(NSString *)query;
+ (NSMutableArray *) fetchResults:(NSString *)query;
+ (int) rowCountForTable:(NSString *)table where:(NSString *)where;
+ (void) errorMessage:(NSString *)msg;
+ (void) closeConnection;




#include <sys/xattr.h>

@interface DBConnection (Private)
- (void) createEditableCopyOfDatabaseIfNeeded;
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL;
- (void) initializeDatabase;
@end

@implementation DBConnection
static DBConnection *conn = NULL;

@synthesize database = g_database;

+ (DBConnection *) sharedConnection 
    if (!conn) 
        conn = [[DBConnection alloc] initConnection];
    
    return conn;


#pragma mark - 
#pragma mark Static Methods

+ (BOOL) executeQuery:(NSString *)query

    BOOL isExecuted = NO;

    sqlite3 *database = [DBConnection sharedConnection].database;
    sqlite3_stmt *statement = nil;

    const char *sql = [query UTF8String];
    if (sqlite3_prepare_v2(database, sql, -1, &statement , NULL) != SQLITE_OK) 
        //NSLog(@"Error: failed to prepare agenda query statement with message '%s'.", sqlite3_errmsg(database));
        //NSString *errorMsg = [NSString stringWithFormat:@"Failed to prepare query statement - '%s'.", sqlite3_errmsg(database)];
        //[DBConnection errorMessage:errorMsg];
        //NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
        return isExecuted;
    

    // Execute the query.
    if(SQLITE_DONE == sqlite3_step(statement)) 
        isExecuted = YES;
    

    // finlize the statement.
    sqlite3_finalize(statement);
    statement = nil;
    return isExecuted;

+ (NSMutableArray *) fetchResults:(NSString *)query

    NSMutableArray *results = [NSMutableArray arrayWithCapacity:0];
    sqlite3 *database = [DBConnection sharedConnection].database;
    sqlite3_stmt *statement = nil;

    const char *sql = [query UTF8String];
    if (sqlite3_prepare_v2(database, sql, -1, &statement , NULL) != SQLITE_OK) 
        //NSLog(@"Error: failed to prepare fetch results statement with message '%s'.", sqlite3_errmsg(database));
        NSString *errorMsg = [NSString stringWithFormat:@"Failed to prepare query statement - '%s'.", sqlite3_errmsg(database)];
        [DBConnection errorMessage:errorMsg];
        //NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
        return results;
    

    while (sqlite3_step(statement) == SQLITE_ROW) 

        id value = nil;
        NSMutableDictionary *rowDict = [NSMutableDictionary dictionaryWithCapacity:0];
        for (int i = 0 ; i < sqlite3_column_count(statement) ; i++) 

            /*
             if (strcasecmp(sqlite3_column_decltype(statement,i),"Boolean") == 0) 
             value = [NSNumber numberWithBool:(BOOL)sqlite3_column_int(statement,i)];
              else */

            if (sqlite3_column_type(statement,i) == SQLITE_INTEGER) 
                value = [NSNumber numberWithInt:(int)sqlite3_column_int(statement,i)];
             else if (sqlite3_column_type(statement,i) == SQLITE_FLOAT) 
                value = [NSNumber numberWithFloat:(float)sqlite3_column_double(statement,i)];                   
             else 

                if (sqlite3_column_text(statement,i) != nil) 
                    value = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement,i)];
                 else 
                    value = @"";
                
            

            if (value) 
                [rowDict setObject:value forKey:[NSString stringWithUTF8String:sqlite3_column_name(statement,i)]];
            
        

        [results addObject:rowDict];
        ////NSLog(@"rowDict -- %@", rowDict);
    

    sqlite3_finalize(statement);
    statement = nil;

    return results;


+ (int) rowCountForTable:(NSString *)table where:(NSString *)where

    int tableCount = 0;
    NSString *query = @"";

    if (where != nil && ![where isEqualToString:@""]) 
        query = [NSString stringWithFormat:@"SELECT COUNT(*) FROM %@ WHERE %@",
                 table,where];
     else 
        [NSString stringWithFormat:@"SELECT COUNT(*) FROM %@",
         table];
        

    sqlite3_stmt *statement = nil;

    sqlite3 *database = [DBConnection sharedConnection].database;
    const char *sql = [query UTF8String];
    if (sqlite3_prepare_v2(database, sql, -1, &statement , NULL) != SQLITE_OK) 
        return 0;
    

    if (sqlite3_step(statement) == SQLITE_ROW)         
        tableCount = sqlite3_column_int(statement,0);
    

    sqlite3_finalize(statement);
    return tableCount;


+ (void) errorMessage:(NSString *)msg

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"ERROR" message:msg delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
    [alert release];


+ (void) closeConnection

    sqlite3 *database = [DBConnection sharedConnection].database;
    if (sqlite3_close(database) != SQLITE_OK) 
        //NSAssert1(0, @"Error: failed to close database with message '%s'.", sqlite3_errmsg(g_database));
        NSString *errorMsg = [NSString stringWithFormat:@"Failed to open database with message - '%s'.", sqlite3_errmsg(database)];
        [DBConnection errorMessage:errorMsg];
    


- (id) initConnection 

    if (self == [super init]) 
        //database = g_database;
        if (g_database == nil) 
            // The application ships with a default database in its bundle. If anything in the application
            // bundle is altered, the code sign will fail. We want the database to be editable by users, 
            // so we need to create a copy of it in the application's Documents directory.     
            [self createEditableCopyOfDatabaseIfNeeded];
            // Call internal method to initialize database connection
            [self initializeDatabase];
        
    
    return self;


// Creates a writable copy of the bundled default database in the application Documents directory.
- (void)createEditableCopyOfDatabaseIfNeeded 
    // First, test for existence.
    BOOL success;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *dbDirectory = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"]]];

    if (![fileManager fileExistsAtPath:dbDirectory]) 
        [fileManager createDirectoryAtPath:dbDirectory withIntermediateDirectories:NO attributes:nil error:nil];
        [self addSkipBackupAttributeToItemAtURL:[[[NSURL alloc] initFileURLWithPath:dbDirectory isDirectory:YES] autorelease]];
    

    NSString *writableDBPath = [dbDirectory stringByAppendingPathComponent:DB_NAME];
    success = [fileManager fileExistsAtPath:writableDBPath];
    if (success) return;
    // The writable database does not exist, so copy the default to the appropriate location.
    NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:DB_NAME];
    success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
    if (!success) 
        //NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);

        NSString *errorMsg = [NSString stringWithFormat:@"Failed to create writable database file with message - %@.", [error localizedDescription]];
        [DBConnection errorMessage:errorMsg];
    


- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL

    const char* filePath = [[URL path] fileSystemRepresentation];

    const char* attrName = "com.apple.MobileBackup";
    u_int8_t attrValue = 1;

    int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
    return result == 0;


// Open the database connection and retrieve minimal information for all objects.
- (void)initializeDatabase 
    // The database is stored in the application bundle. 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);

    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *dbDirectory = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"]]];


    NSString *path = [dbDirectory stringByAppendingPathComponent:DB_NAME];
    ////NSLog(@"SQLite Root: %s", [path UTF8String]);

    // Open the database. The database was prepared outside the application.
    if (sqlite3_open([path UTF8String], &g_database) != SQLITE_OK) 
        // Even though the open failed, call close to properly clean up resources.
        sqlite3_close(g_database);
        g_database = nil;
        //NSAssert1(0, @"Failed to open database with message '%s'.", sqlite3_errmsg(g_database));
        NSString *errorMsg = [NSString stringWithFormat:@"Failed to open database with message - '%s'.", sqlite3_errmsg(g_database)];
        [DBConnection errorMessage:errorMsg];
    


// Save all changes to the database, then close it.
- (void)close 

    if (g_database) 
        // Close the database.
        if (sqlite3_close(g_database) != SQLITE_OK) 
            //NSAssert1(0, @"Error: failed to close database with message '%s'.", sqlite3_errmsg(g_database));
            NSString *errorMsg = [NSString stringWithFormat:@"Failed to open database with message - '%s'.", sqlite3_errmsg(g_database)];
            [DBConnection errorMessage:errorMsg];
        
        g_database = nil;
    


- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application 
    // "dehydrate" all data objects - flushes changes back to the database, removes objects from memory

请提供适用于我的代码的任何建议和源代码..

谢谢……

【问题讨论】:

您遇到什么错误?在不知道错误是什么的情况下,我们无法提供任何帮助。 请解释您遇到的错误是什么 【参考方案1】:

我建议你使用FMDB - 一个客观的 C 语言包装器。这很容易,并且会节省您的大量精力。

【讨论】:

【参考方案2】:

我同意选择一个开源库作为开始,特别是如果您是初学者。这是我写的一个针对初学者的 SQLite 库:TankDB

有很多示例可供查看,以便能够快速实现您在上面尝试做的事情。

【讨论】:

以上是关于如何从我的 sqlite 数据库中获取数据的主要内容,如果未能解决你的问题,请参考以下文章

使用 Core Data 一对多关系从 JSON 数组填充 sqlite 数据库

如何从我的流中获取数据并使用它?

SQLite - 如何使用 ROW_NUMBER() OVER

如何使用从我的 SQLite 数据库中检索到的数据填充 tkinter 下拉框?

如何使用两个日期选择器从我的数据库中获取数据。代码点火器

如何获取数据库中的表信息(SQLite)[重复]