IOS中数据存储 sqlite3 的应用

   相比于服务器端的数据存储,IOS中几种数据存储的技术:

    (1)XML属性列表 —— PList
    (2)NSKeyedArchiver 归档
    (3)Preference(偏好设置)
    (4)SQLite3
    (5)Core Data(以面向对象的方式操作数据库SQLite)
     发现用数据库进行数据的存储和缓存,才是王道, 比较有心得的体会:虽然通过文件的方式进行存储,读写速度相对数据库存储较快,但是涉及大批量的数据时,在查询/管理/优化方面,数据库的优势明显会更大些.而且作为移动端,SQLite数据库在数据缓存方面的运用则尤为重要.
     工作之余,运用SQLite3的许多小知识点,写了一个小小的数据库增删改查操作,专门与sqlite3交互的个人信息管理类,直接上代码,望大牛指正:
 
   
                                                                                       底层架构图
 
 核心代码实现:
(1) Services服务层封装
 PesonManager.h
#import <Foundation/Foundation.h>
#import "Person.h"

@interface PersonManager : NSObject

+ (instancetype)sharedPersonManager;

// 1. 新增用户
- (void)addPerson:(Person *)person;

// 2. 更新用户(关于主键,永远都不要去修改)
- (void)updatePerson:(Person *)person;

// 3. 删除用户,使用主键来删除指定用户
- (void)removePerson:(NSInteger)personID;

// 4. 列表用户,查询所有用户
- (NSArray *)allPersons;

@end

 PesonManager.m 

#import "PersonManager.h"
#import <sqlite3.h>
#import "NSString+JH.h"

// 全局变量
static PersonManager *_instance;

@interface PersonManager()
{
    // 全局的数据库句柄
    sqlite3 *_db;
}

@end

@implementation PersonManager

#pragma mark - 单例的方法
+ (id)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
 
    return _instance;
}

+ (instancetype)sharedPersonManager
{
    if (_instance == nil) {
        _instance = [[PersonManager alloc] init];
    }
    
    return _instance;
}

#pragma mark - 类方法
- (id)init
{
    self = [super init];
    
    // 懒加载数据库连接及创建数据表
    if (self) {
        // 1. 打开数据库
        [self openDB];
        // 2. 创建数据表
        [self createTable];
    }
    
    return self;
}

#pragma mark 打开数据库
- (void)openDB
{
  
    NSString *dbPath = [@"T_Person.db" appendDocumentDir];
    _db = NULL;
    
    if (SQLITE_OK == sqlite3_open([dbPath UTF8String], &_db)) {
        NSLog(@"数据库打开成功");
    } else {
        NSLog(@"数据库打开失败");
    }
}

#pragma mark 单步执行SQL
- (void)execSQL:(NSString *)sql message:(NSString *)message
{
    char *errmsg = NULL;
    if (SQLITE_OK == sqlite3_exec(_db, [sql UTF8String], NULL, NULL, &errmsg)) {
        NSLog(@"%@成功!", message);
    } else {
        NSLog(@"%@失败 - %s", message, errmsg);
    }
}

#pragma mark 创建数据表
- (void)createTable
{
    NSString *sql = @"CREATE TABLE IF NOT EXISTS T_Person (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT, gender INTEGER, age INTEGER, height REAL)";
    
    [self execSQL:sql message:@"创建数据表"];
}

- (void)addPerson:(Person *)person
{
// 1. SQL NSString *sql = [NSString stringWithFormat:@"INSERT INTO T_Person (name, gender, age, height) VALUES ('%@', %d, %d, %f)", person.name, person.gender, person.age, person.height]; [self execSQL:sql message:@"新增个人记录"]; } // 2. 更新用户(关于主键,永远都不要去修改) - (void)updatePerson:(Person *)person where: (NSStirng *)where { NSString *sql = [NSString stringWithFormat:@"UPDATE T_Person SET name = '%@', gender = %d, age = %d, height = %f where %@", person.name, person.gender, person.age, person.height , where]; [self execSQL:sql message:@"更新个人记录"]; } // 3. 删除用户,使用主键来删除指定用户 - (void)removePerson:(NSInteger)personID { NSString *sql =[NSString stringWithFormat: @"delete * from T_Person where id =%@",personID]; [self execSQL:sql message:@"删除记录成功"]; } // 4. 列表用户,查询所有用户 - (NSArray *)allPersons { NSString *sql = @"SELECT id, name, age, gender, height FROM T_Person ORDER BY name"; sqlite3_stmt *stmt = NULL; NSMutableArray *arrayM = [NSMutableArray array]; NSMutableArray *persons = nil; if (SQLITE_OK == sqlite3_prepare_v2(_db, [sql UTF8String], -1, &stmt, NULL)) { persons = [NSMutableArray array]; while (SQLITE_ROW == sqlite3_step(stmt)) { int ID = sqlite3_column_int(stmt, 0); const unsigned char *name = sqlite3_column_text(stmt, 1); int age = sqlite3_column_int(stmt, 2); int gender = sqlite3_column_int(stmt, 3); CGFloat height = sqlite3_column_double(stmt, 4); // const unsigned char *直接输出看不出结果,需要转换 NSString *nameUTF8 = [NSString stringWithUTF8String:(const char *)name]; Person *p = [Person personWithID:ID name:nameUTF8 age:age gender:gender height:height]; [persons addObject:p]; } } else { NSLog(@"语法错误"); } return persons; } @end

 接下来在控制器里面封装模型取出相应数据即可,关于SQLite3中运用的知识点,总结如下:

1.  sqlite3_open 打开数据库
    * 如果数据库已经存在,直接打开
    * 如果数据库不存在,新建一个空白的数据库(0KB),然后再打开
 
 2. 创建数据表
    * 定义数据操作SQL
    * 调用sqlite3_exec执行SQL
    提示:为了避免重复建表,可以在建表SQL中增加 IF NOT EXISTS
 
 3. 单步执行操作
    增/删/改/查数据

 4. 查询语句
 1> 准备SQL
 2> 检查SQL语句是否正确                     sqlite3_prepare_v2
 3> 单步执行,依次获取查询到的记录             SQLITE_ROW == sqlite3_step...
 4> 按照查询顺序,依次取出每一个字段的内容
     sqlite3_column_text 取字符串
     sqlite3_column_int 取整数
     sqlite3_column_double 取浮点数
 
 5.操作SQLite数据库需要5个方法
    sqlite3_open
    sqlite3_exec
 
    sqlite3_prepare_v2
    sqlite3_step
 
    sqlite3_column_text 取字符串
    sqlite3_column_int 取整数
    sqlite3_column_double 取浮点数
 两个枚举
    SQLITE_OK
    SQLITE_ROW

      当然,一般在实际开发中都会直接封装成一套数据库操作类,但是对于SQL结构化查询,无论是服务器开发,还是客户端开发,都是万变不离其中.最后,十分感谢大牛LF的讲解与分享.

posted @ 2014-05-16 20:39  Victor·旋  阅读(472)  评论(0编辑  收藏  举报