iOS数据存储之SqLite3
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