首页 > 代码库 > IOS中数据存储 sqlite3 的应用, 知识点: 数据库句柄 , 单例模式运用, Services服务层,sqlite3_open, sqlite3_exec, sqlite3_prepare_v2,sqlite3_step等等

IOS中数据存储 sqlite3 的应用, 知识点: 数据库句柄 , 单例模式运用, Services服务层,sqlite3_open, sqlite3_exec, sqlite3_prepare_v2,sqlite3_step等等

   相比于服务器端的数据存储,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 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#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
{<br> // 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结构化查询,无论是服务器开发,还是客户端开发,都是万变不离其中.