iOS - 使用 SQLite 数据库实现数据持久化
前言
SQLite 是一款主流的嵌入式关系型数据库,它的主要特点是轻量级和跨平台,是当前很多嵌入式操作系统中数据库的首选。
数据库也是客户端开发中常用的一种数据持久化手段,本文主要介绍在客户端开发中常用的数据库 SQLite,结合一个简单的理解讲解它引入、创建到后面 CRUD 的操作。
文章目录
- 前言
- 1. sqlite3 引入
- 2. sqlite3 的使用
- 2.1 VGUserDAO 的封装
- 2.2 建表操作
- 2.3 查询操作
- 2.4 插入操作
- 2.5 修改操作
- 2.6 删除操作
- 参考资料
1. sqlite3 引入
要想在 iOS 开发中使用 SQLite 数据库,先要导入 libsqlite3.tbd。具体路径是 TARGETS -> Build Phases -> Link Binary With Libraries。操作如下图所示:
2. sqlite3 的使用
这里以一个简单的例子来介绍 sqlite3 的使用,我们有个用户表,里面有用户id,用户名称和用户年龄等三个字段,我们使用 sqlite3 对它进行增删改查。
下面是用户类的定义:
@interface VGUser : NSObject// 用户ID @property (nonatomic, copy) NSString *userId; // 用户名 @property (nonatomic, copy) NSString *userName; // 用户年龄 @property (nonatomic, assign) NSInteger userAge;- (instancetype)initWithUserId:(NSString *)userIduserName:(NSString *)userNameuserAge:(NSInteger)userAge;@end2.1 VGUserDAO 的封装
为了满足我们的需求,我们封装一个 VGUserDAO 类来实现我们要的操作,主要实现下面方法:
@interface VGUserDAO : NSObject/// 获取 VGUserDAO 单例 + (instancetype)sheredInstance;/// 查找特定ID的用户 - (VGUser *)findById:(NSString *)userId;/// 查询所有用户 - (NSArray *)findAll;/// 在数据表中插入一行数据 - (void)create:(VGUser *)user;/// 删除特定ID的用户 - (void)remove:(NSString *)userId;/// 修改用户信息 - (void)modify:(VGUser *)user;@endVGUserDAO.m 文件的部分代码
#import "VGUser.h" #import <sqlite3.h>#define DBFILE_NAME @"UserList.sqlite3"@interface VGUserDAO () {sqlite3 *_db; // 数据库对象 }// 数据库的存储路径 @property (nonatomic, strong) NSString *plistFilePath;@end@implementation VGUserDAO+ (instancetype)sheredInstance {static VGUserDAO *sharedInstance = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^ {sharedInstance = [[VGUserDAO alloc] init];// 设置数据库的存储路径sharedInstance.plistFilePath = [sharedInstance applicationDocumentsDirectory];// 执行检表操作[sharedInstance createEditableDatabaseIfNeed];});return sharedInstance; }// 获取数据库的存储路径 - (NSString *)applicationDocumentsDirectory {NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, TRUE) lastObject];NSString *path = [docDir stringByAppendingPathComponent:DBFILE_NAME];return path; }//......@end2.2 建表操作
建表操作主要包含以下几个步骤:
- 使用 sqlite3_open 函数打开数据库
- 使用 sqlite3_exec 函数执行建表的 SQL 语句,创建用户表
- 使用 sqlite3_close 函数关闭数据库,释放资源
具体的代码实现如下:
- (void)createEditableDatabaseIfNeed {const char *cpath = self.plistFilePath.UTF8String;// sqlite3_open// 1. filename 是数据库文件的完整路径// 2. ppDb 是sqlite3类型指针变量的地址if (sqlite3_open(cpath, &_db) != SQLITE_OK) {NSLog(@"数据库打开失败");} else {NSString *sql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS User (user_id TEXT PRIMARY KEY, user_name TEXT, user_age INTEGER);"];const char *cSql = sql.UTF8String;// sqlite3_exec// 1. sqlite3类型指针变量,表示数据库// 2. sql 是要执行的sql语句// 3. 要回调的函数指针// 4. 要回调的函数的第一个参数// 5. 执行出错信息的字符串if (sqlite3_exec(_db, cSql, NULL, NULL, NULL) != SQLITE_OK) {NSLog(@"建表失败");}}// 关闭数据库sqlite3_close(_db); }建表的时候需要指定数据类型,SQLite 支持的常见数据类型如下所示:
- integer,有符号的整数类型
- real,浮点数
- text,字符串类型,采用 UTF-8 和 UTF-16 编码
- blob,二进制大对象类型,能够存放任何二进制数据
2.3 查询操作
使用 sqlite3 执行查询操作,主要包括如下步骤:
- 使用 sqlite3_open 函数打开数据库
- 使用 sqlite3_prepare_v2 函数预处理 SQL 语句
- 使用 sqlite3_bind_text 等函数绑定参数
- 使用 sqlite3_step 函数执行 SQL 语句
- 使用 sqlite3_column_text 等函数提取结果集中的字段
- 使用 sqlite3_finalize 和 sqlite3_close 函数释放资源
下面是对根据 ID 查询特定用户的方法的实现:
- (VGUser *)findById:(NSString *)userId {const char *cpath = self.plistFilePath.UTF8String;if (sqlite3_open(cpath, &_db) != SQLITE_OK) {NSLog(@"数据库打开失败");} else {NSString *sql = @"select user_id, user_name, user_age from user where user_id = ?";const char *cSql = sql.UTF8String;// 语句对象sqlite3_stmt *statement;// sqlite3_prepare_v2 SQL预处理函数// 1. db 是sqlite3类型指针变量,表示数据库// 2. zSql 是要执行的SQL语句// 3. nByte 是全部SQL字符串的最大长度// 4. ppStmt 是sqlite3_stmt类型指针的地址,表示语句对象// 5. pzTail 是zSql没有执行部分if (sqlite3_prepare_v2(_db, cSql, -1, &statement, NULL) == SQLITE_OK) {const char *cUserId = userId.UTF8String;// sqlite3_bind_text 绑定SQL语句TEXT类型的参数// 1. sqlite3_stmt类型指针// 2. 参数的序号,从 1 开始// 3. 参数的值// 4. 字符串长度// 5. 函数指针sqlite3_bind_text(statement, 1, cUserId, -1, NULL);// sqlite3_step 执行语句if (sqlite3_step(statement) == SQLITE_ROW) {// sqlite3_column_text 读取字符串类型数据// 1. 语句对象// 2. SELECT字段的索引,从 0 开始char *bufUserId = (char *)sqlite3_column_text(statement, 0);char *bufUserName = (char *)sqlite3_column_text(statement, 1);// sqlite3_column_int 读取int类型数据int bufUserAge = sqlite3_column_int(statement, 2);NSString *strUserId = [[NSString alloc] initWithUTF8String:bufUserId];NSString *strUserName = [[NSString alloc] initWithUTF8String:bufUserName];VGUser *user = [[VGUser alloc] initWithUserId:strUserIduserName:strUserNameuserAge:bufUserAge];// 释放语句对象sqlite3_finalize(statement);sqlite3_close(_db);return user;}}sqlite3_finalize(statement);}sqlite3_close(_db);return nil; }下面是对查找所有用户的方法的实现:
- (NSArray *)findAll {const char *cpath = self.plistFilePath.UTF8String;NSMutableArray *userList = [NSMutableArray array];if (sqlite3_open(cpath, &_db) != SQLITE_OK) {NSLog(@"数据库打开失败");} else {NSString *sql = @"select user_id, user_name, user_age from user";const char *cSql = sql.UTF8String;sqlite3_stmt *statement;if (sqlite3_prepare_v2(_db, cSql, -1, &statement, NULL) == SQLITE_OK) {// 常量 SQLITE_ROW 表示结果集中还有数据while (sqlite3_step(statement) == SQLITE_ROW) {char *bufUserId = (char *)sqlite3_column_text(statement, 0);char *bufUserName = (char *)sqlite3_column_text(statement, 1);int bufUserAge = sqlite3_column_int(statement, 2);NSString *strUserId = [[NSString alloc] initWithUTF8String:bufUserId];NSString *strUserName = [[NSString alloc] initWithUTF8String:bufUserName];VGUser *user = [[VGUser alloc] initWithUserId:strUserIduserName:strUserNameuserAge:bufUserAge];[userList addObject:user];}}sqlite3_finalize(statement);}sqlite3_close(_db);return [userList copy]; }在进行字段读取的时候,根据字段类型的不同,有下面几种常用函数:
- sqlite3_column_int()
- sqlite3_column_int64()
- sqlite3_column_double()
- sqlite3_column_text()
- sqlite3_column_text16()
- sqlite3_column_blob()
我们可以根据字段的类型,选择合适的函数。参数绑定函数 sqlite3_bind_text 也是同理。
2.4 插入操作
使用 sqlite3 执行插入操作,主要包含如下步骤:
- 使用 sqlite3_open 函数打开数据库
- 使用 sqlite3_prepare_v2 函数预处理 SQL 语句
- 使用 sqlite3_bind_text 等函数绑定参数
- 使用 sqlite3_step 函数执行 SQL 语句
- 使用 sqlite3_finalize 和 sqlite3_close 函数释放资源
2.5 修改操作
对与修改操作而言,已经没有新东西可言了,主要差别还是在 SQL 语句,插入、修改和删除用的分别是 insert、 update 和 delete。
- (void)modify:(VGUser *)user {const char *cpath = self.plistFilePath.UTF8String;if (sqlite3_open(cpath, &_db) != SQLITE_OK) {NSLog(@"数据库打开失败");} else {NSString *sql = @"update user set user_name = ?, user_age = ? where user_id = ?";const char *cSql = sql.UTF8String;sqlite3_stmt *statement;if (sqlite3_prepare_v2(_db, cSql, -1, &statement, NULL) == SQLITE_OK) {const char *cUserId = user.userId.UTF8String;const char *cUserName = user.userName.UTF8String;const int cUserAge = (int)user.userAge;sqlite3_bind_text(statement, 1, cUserName, -1, NULL);sqlite3_bind_int(statement, 2, cUserAge);sqlite3_bind_text(statement, 3, cUserId, -1, NULL);if (sqlite3_step(statement) != SQLITE_DONE) {NSLog(@"数据修改失败");}}sqlite3_finalize(statement);}sqlite3_close(_db); }2.6 删除操作
- (void)remove:(NSString *)userId {const char *cpath = self.plistFilePath.UTF8String;if (sqlite3_open(cpath, &_db) != SQLITE_OK) {NSLog(@"数据库打开失败");} else {NSString *sql = @"delete from user where user_id = ?";const char *cSql = sql.UTF8String;sqlite3_stmt *statement;if (sqlite3_prepare_v2(_db, cSql, -1, &statement, NULL) == SQLITE_OK) {const char *cUserId = userId.UTF8String;sqlite3_bind_text(statement, 1, cUserId, -1, NULL);if (sqlite3_step(statement) != SQLITE_DONE) {NSLog(@"数据删除失败");}}sqlite3_finalize(statement);}sqlite3_close(_db); }参考资料
- 《iOS开发指南:从Hello World到App Store上架(第5版)》
总结
以上是生活随笔为你收集整理的iOS - 使用 SQLite 数据库实现数据持久化的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: iOS - 沙盒文件操作指南
- 下一篇: mysql中日期相减_如何使用MySQL