数据缓存——SQLite关系型数据库的使用(补充)

封装使用代码示例
1 .h 文件

#import <Foundation/Foundation.h>

@interface SQliteManager : NSObject

+ (instancetype)shareSQLite;

/// 建表/删表/插入数据/更新数据/删除数据 等操作
- (BOOL)executeSQLite:(NSString *)sqlString;
/// 查询操作
- (NSArray *)selectSQLite:(NSString *)sqlString;

@end

2 .m 文件

#import "SQliteManager.h"
#import <sqlite3.h>  

/// 存储文件
static NSString *const SQLiteFile = @"SQLiteFile.db";
//static NSString *const SQLiteFile = @"SQLiteFile.sqlite3";

@interface SQliteManager ()
{
    // 数据库
    sqlite3 *dataBase;
    BOOL isOpenDataBase;
}

@property (nonatomic, strong) NSString *filePath;

@end

@implementation SQliteManager

- (instancetype)init
{
    self = [super init];
    if (self) {
        NSLog(@"filePath = %@", self.filePath);
    }
    return self;
}

+ (instancetype)shareSQLite
{
    static SQliteManager *staticSQliteManager;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        staticSQliteManager = [[self alloc] init];
        assert(staticSQliteManager != nil);
    });
    return staticSQliteManager;
}

#pragma mark -

- (BOOL)isValidSQL:(NSString *)sql
{
    return (sql && [sql isKindOfClass:NSString.class] && sql.length > 0);
}

- (NSString *)filePath
{
    if (_filePath == nil) {
        // doucment
//        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
//        NSString *filePath = [paths objectAtIndex:0];
        // 缓存
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        _filePath = [paths objectAtIndex:0];
        _filePath = [_filePath stringByAppendingPathComponent:SQLiteFile];
        NSLog(@"filepath: %@", _filePath);
    }
    return _filePath;
}

- (BOOL)openSQLite
{
    const char *fileName = self.filePath.UTF8String;
    int execStatus = sqlite3_open(fileName, &dataBase);
    if (execStatus == SQLITE_OK) {
        NSLog(@"数据库打开成功");
        isOpenDataBase = YES;
        return YES;
    } else {
        NSLog(@"数据库打开失败:%s", sqlite3_errmsg(dataBase));
        isOpenDataBase = NO;
        return NO;
    }
}

- (void)closeSQLite
{
    if (isOpenDataBase) {
        // 关闭数据库
        isOpenDataBase = NO;
        int execStatus = sqlite3_close(dataBase);
        if (execStatus == SQLITE_OK) {
            NSLog(@"数据库关闭成功");
        } else {
            NSLog(@"数据库关闭失败:%s", sqlite3_errmsg(dataBase));
        }
    }
}

int callback(void *param, int f_num, char **f_value, char **f_name)
{
    printf("%s:这是回调函数!\n", __FUNCTION__);
    return 0;
}

- (BOOL)executeSQLite:(NSString *)sqlString
{
    BOOL result = NO;
    @synchronized (self) {
        if ([self isValidSQL:sqlString]) {
            if (self.openSQLite) {
                char *errorMsg;
                int execStatus = sqlite3_exec(dataBase, sqlString.UTF8String, callback, NULL, &errorMsg);
                if (execStatus == SQLITE_OK) {
                    NSLog(@"[%@]执行成功", sqlString);
                    result = YES;
                } else {
                    NSLog(@"[%@]执行失败:%s", sqlString, errorMsg);
                }
                [self closeSQLite];
            }
        }
    }
    return result;
}

- (NSArray *)selectSQLite:(NSString *)sqlString
{
    NSMutableArray *array = [[NSMutableArray alloc] init];
    if ([self isValidSQL:sqlString]) {
        if (self.openSQLite) {
            sqlite3_stmt *statement;
            int execStatus = sqlite3_prepare_v2(dataBase, sqlString.UTF8String, -1, &statement, NULL);
            if (execStatus == SQLITE_OK) {
            	// 循环判断,取得数据集合
                while (sqlite3_step(statement) == SQLITE_ROW) {
                	// 根据数据类型,及字段所有列数获取信息(列数从0~n)
                    int index = sqlite3_column_int(statement, 0);
                    char *name = (char *)sqlite3_column_text(statement, 1);
                    char *gender = (char *)sqlite3_column_text(statement, 2);
                    int age = sqlite3_column_int(statement, 3);
                    char *education = (char *)sqlite3_column_text(statement, 4);
                    //
                    NSString *idStr = [[NSString alloc] initWithFormat:@"%d", index];
                    NSString *nameStr = [[NSString alloc] initWithUTF8String:name];
                    NSString *sexStr = [[NSString alloc] initWithUTF8String:gender];
                    NSString *ageStr = [[NSString alloc] initWithFormat:@"%d", age];
                    NSString *eduStr = [[NSString alloc] initWithUTF8String:education];
                    //
                    NSDictionary *dict = @{@"personId":idStr, @"personName":nameStr, @"personGender":sexStr, @"personAge":ageStr, @"personEducation":eduStr};
                    [array addObject:dict];
                }
            }
            // 释放sqlite3_stmt对象资源
            sqlite3_finalize(statement);
            [self closeSQLite];
        }
    }
    return array;
}

@end

3 使用及注意事项

// 创建表
NSString *sql = @"CREATE TABLE IF NOT EXISTS PERSON (id INTEGER PRIMARY KEY, name TEXT, gender TEXT, age INTEGER, education TEXT)";
[SQliteManager.shareSQLite executeSQLite:sql];

定义字段及其类型(NULLNULL 值,INTEGER整数,REAL8字节浮点值,TEXTUTF8编码文本字符串,BLOB blob 数据,完全根据它的输入存储),并使用PRIMARY KEY定义表中的关键字

// 删除表
NSString *sql = @"DROP TABLE PERSON";
[SQliteManager.shareSQLite executeSQLite:sql];
// 插入数据
NSString *sql = [NSString stringWithFormat:@"insert into PERSON (id, name, gender, age, education) values (NULL, \"%@\", \"%@\", \"%d\", \"%@\")", @"devZhang", @"男", 26, @"本科"];
[SQliteManager.shareSQLite executeSQLite:sql];

values 中对应字段值,需要使用单引号``,或双引号"",否则会报异常,从而导致sql 语句执行失败

// 更新数据
NSString *sql = [NSString stringWithFormat:@"UPDATE PERSON SET education = '%@' where name = '%@'", @"学士", @"devZhang"];
[SQliteManager.shareSQLite executeSQLite:sql];
// 删除数据,指定数据
 NSString *sql = [NSString stringWithFormat:@"DELETE FROM PERSON where NAME = '%@'", @"devZhang"];
// 或 删除所有数据
NSString *sql = @"DELETE FROM PERSON";
[SQliteManager.shareSQLite executeSQLite:sql];
// 查找数据,指定数据
NSString *sql = @"SELECT * FROM PERSON where name = 'devZhang'";
// 或 查找所有数据
NSString *sql = @"SELECT * FROM PERSON";
NSArray *array = [SQliteManager.shareSQLite selectSQLite:sql];
NSLog(@"select: %@", array);

4 说明

  • sqlite3_exec函数只能用于创建表、删除表、插入数据、更新数据、删除数据等的操作,而不能用于查找数据操作。
  • 查找数据操作相对复杂,即查找的数据可能是一条数据记录,也可能是一个数据集合,故在查找操作时,需要多个函数配合使用,如sqlite3_prepare_v2sqlite3_stepsqlite3_column_intsqlite3_column_text等。
  • 注意资源的释放,避免造成使用异常,如:sqlite3数据库打开sqlite3_open VS 关闭sqlite3_closesqlite3_stmt资源打开sqlite3_prepare_v2 VS 释放sqlite3_finalize
发布了804 篇原创文章 · 获赞 135 · 访问量 142万+

猜你喜欢

转载自blog.csdn.net/potato512/article/details/103431337