iOS中数据存储的方式有很多中,当数据量较大的时候偏好设置,归档和plist就无法满足需求了
这时候就需要用SqLite或者CoreData来存储数据
下面就来介绍一下如何使用SqLite存储数据
要使用Sqlite必须引入libSqlite3.dylib库
要使用首先要有一个handle句柄(handle句柄,在C语言中,通常把用于控制某类东西的叫做句柄,实际上是一个指针。)
// 数据库句柄
sqlite3 *_db;
SqLite存储数据时也是存在一个文件中的,只不过这个文件格式是定制的,可以让SqLite快速查询到其需要的数据
所以如果要使用SqLite数据库首先要创建一个数据库文件,所以要有一个文件路径
// 一个NSString分类
- (NSString *)appendDocumentDir
{
NSString *docDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
return [docDir stringByAppendingPathComponent:self];
}
// 设置沙盒中的文件路径
// 提示:在自己开发中,不要用.db结尾的sqlite数据库文件名
NSString *dbPath = [@"readme.db" appendDocumentDir];
NSLog(@"%@", dbPath);
上面创建了我们存储数据库文件的路径dbPath
下面我们就开始创建这个存储文件
/**
sqlite3_open
1) 如果数据库存在,直接打开
2) 如果数据库不存在,先创建数据库文件,再打开
*/
_db = NULL;
if (SQLITE_OK == sqlite3_open([dbPath UTF8String], &_db)) {
NSLog(@"数据库打开成功");
} else {
NSLog(@"数据库打开失败");
}
调用sqlite3_open函数就会创建或者打开一个数据库,如果指定路径已经存在数据库就会打开这个数据库,如果指定的dbPath不存在数据库就会创建一个数据库然后打开,创建或者打开的时候一是要传入路径,二是要传入句柄,因为后面的数据库增删改查都要靠句柄来干活.
上面代码中的SQLITE_OK是SqLite操作结果的返回码,具体含义可以参照头文件或者帮助文档
此时我们就有了一个可以操作的数据库了,有了数据库以后第一件事肯定是建一张表
#pragma mark 创建数据表
- (void)createTable
{
// 避免重复建表的思路
// 1. 检查沙盒,判断数据库文件是否存在,如果存在就不再建表;
// 2. 数据库的方法:IF NOT EXISTS,放在表名之前即可
// 定义SQL语句
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:@"创建数据表"];
}
#pragma mark 单步执行SQL
- (void)execSQL:(NSString *)sql message:(NSString *)message
{
// 执行SQL语句
/**
1> 数据库句柄
2> 要执行的SQL语句
3> 回调:SQL指令执行完成后,调用的函数,就叫做回调函数
4> 回调函数的第一个参数
5> SQL语句执行的出错信息
*/
char *errmsg = NULL;
if (SQLITE_OK == sqlite3_exec(_db, [sql UTF8String], NULL, NULL, &errmsg)) {
NSLog(@"%@成功!", message);
} else {
// C语言中字符串输出应该用%s
NSLog(@"%@失败 - %s", message, errmsg);
}
}
第一个方法是创建好建表语句,然后交给第二个我方法去执行建表操作
关于建表语句:CREATE TABLE IF NOT EXISTS没有这张表时才创建,如果有问题会及时发现
表名称一般以T_开头,防止与关键字或者类名变量名冲突
sqlite3_exec函数可以执行SQL语句,从而对数据库进行操作
第一个参数是操作数据库用的句柄,第二个参数是执行的sql语句,第三四个参数是回调相关的参数,最后一个是错误信息
如果打印出成功信息建表就成功了.
然后增删改功能照着上面的代码写好SQL语句,直接调用就可以了,下面看看查询时该怎么写代码
- (void)allPersons
{
// 1. SQL
NSString *sql = @"SELECT id, name, age, gender, height FROM T_Person";
// 2. 查询语句通常是使用字符串拼接出来的
// 因此,在正常使用查询语句之前,需要检查SQL语句的语法正确!
sqlite3_stmt *stmt = NULL;
if (SQLITE_OK == sqlite3_prepare_v2(_db, [sql UTF8String], -1, &stmt, NULL)) {
NSLog(@"语法正确");
// 利用句柄,逐一查询符合条件的数据
// sqlite3_step 每次提取一条查询的记录行,不断重复,一直取到最后一条记录位置
while (SQLITE_ROW == sqlite3_step(stmt)) {
// 取到行信息,逐一获取每一列的内容
// iCol对应的就是SQL语句中字段的顺序,从0开始
// 根据实际查询字段的属性,使用sqlite3_column_xxx取得对应的内容即可
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];
NSLog(@"%@", p);
}
} else {
NSLog(@"语法错误");
}
}
查询的时候基本步骤就是:1.创建查询语句
2.创建sqlite3_stmt结果集
3.用sqlite3_prepare_v2函数建立结果集和操作句柄之间的关系,并且检查语法
4.while (SQLITE_ROW == sqlite3_step(stmt)) 循环判断并且从中取出数据
5.sqlite3_column_int(stmt, 0);用类似函数取出数据,第二个参数是所在
其他关于数据库主键,外键和其他约束的请查阅sqlite资料
另外有一个SQLite的第三方类库FMDB,有兴趣的可以去github上搜一下
x