`

iOS数据持久化-SQLite数据库使用详解

阅读更多

使用SQLite数据库

创建数据库

创建数据库过程需要3个步骤:

1、使用sqlite3_open函数打开数据库;

2、使用sqlite3_exec函数执行Create Table语句,创建数据库表;

3、使用sqlite3_close函数释放资源。

 

这个过程中使用了3个SQLite3函数,它们都是纯C语言函数,通过Objective-C去调用C函数当然不是什么问题,但是也要注意Objective-C数据类型与C数据类型兼容性问题。

下 面我们使用SQLite技术实现备忘录案例,与属性列表文件实现一样,我们只需要修改持久层工程(PersistenceLayer)中NoteDAO类 就可以了。首先我们需要添加SQLite3库到工程环境中,有3个工程需要添加到哪个呢?应该添加到可以运行的工程即表示层工程 PresentationLayer。选择工程PresentationLayer中 TARGETS→PresentationLayer→Link Binary With Libraries,点击左下角的“+”,弹出对话框选择 libsqlite3.dylib或libsqlite3.0.dylib,在弹出的对话框中点击Add添加。

1

NoteDAO.h文件的修改:

#import ”Note.h”

#import ”sqlite3.h”

 

#define DBFILE_NAME @”NotesList.sqlite3″

 

@interface NoteDAO : NSObject

{

sqlite3 *db;

}

 

+ (NoteDAO*)sharedManager;

 

- (NSString *)applicationDocumentsDirectoryFile;

- (void)createEditableCopyOfDatabaseIfNeeded;

 

//插入Note方法

-(int) create:(Note*)model;

 

//删除Note方法

-(int) remove:(Note*)model;

 

//修改Note方法

-(int) modify:(Note*)model;

 

//查询所有数据方法

-(NSMutableArray*) findAll;

 

//按照主键查询数据方法

-(Note*) findById:(Note*)model;

 

@end



我们需要使用语句#import ”sqlite3.h”引入sqlite3头文件,而且需要定义sqlite3*成员变量db。NoteDAO.m中的createEditableCopyOfDatabaseIfNeeded方法:

- (void)createEditableCopyOfDatabaseIfNeeded {

 

NSString *writableDBPath = [self applicationDocumentsDirectoryFile];

if (sqlite3_open([writableDBPath UTF8String], &db) != SQLITE_OK) { ①

sqlite3_close(db);  ②

NSAssert(NO,@”数据库打开失败。”);

} else {

char *err;

NSString *createSQL = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS Note

(cdate TEXT PRIMARY KEY, content TEXT);"]; ③

if (sqlite3_exec(db,[createSQL UTF8String],NULL,NULL,&err) != SQLITE_OK) { ④

sqlite3_close(db); ⑤

NSAssert1(NO, @”建表失败, %s”, err);  ⑥

}

sqlite3_close(db);  ⑦

}

}



createEditableCopyOfDatabaseIfNeeded方法用于创建数据库,第1步打开数据 库,代码①行,语句是 sqlite3_open([writableDBPath UTF8String], &db),sqlite3_open函数的第1个参数是 数据库文件完整的路径,但是需要注意的是在SQLite3函数中接受的是char*的UTF-8类型数据,需要将NSString*转换为UTF-8,使 用NSString*的UTF8String方法可以转换,sqlite3_open函数第2个参数sqlite3指针变量db的地址。该函数的返回值是 int类型,在SQLite3中定义了很多常量,返回值等于常量SQLITE_OK则说明操作成功。

第2步执行建表语句,代码第④行,语句 sqlite3_exec(db,[createSQL UTF8String],NULL,NULL,&err)执行建表的SQL。第1个参数 是sqlite3指针变量db的地址,第2个参数是要执行的sql语句,第3个参数是要回调函数,第4个参数是要回调函数的参数,第5个参数是执行出错的 字符串。建表SQL语句是,如果表Note存在这不用创建。

CREATE TABLE IF NOT EXISTS Note (cdate TEXT PRIMARY KEY, content TEXT)

第3步使用sqlite3_close函数释放资源,代码②、⑤、⑦行所示,在数据库打开失败、Create Table执行失败和成功执行完成时候调用。原则上无论正常结束还是异常结束必须使用sqlite3_close函数释放资源。

查询数据

数据查询一般会带有查询条件,这个使用SQL语句where子句很容易实现,但是在程序中需要动态绑定参数给where子句。执行查询数据步骤如下:

1、使用sqlite3_open函数打开数据库;

2、使用sqlite3_prepare_v2函数预处理SQL语句;

3、使用sqlite3_bind_text函数绑定参数;

4、使用sqlite3_step函数执行SQL语句,遍历结果集;

5、使用sqlite3_column_text等函数提取字段数据;

6、使用sqlite3_finalize和sqlite3_close函数释放资源。

NoteDAO.m中的按照主键查询数据方法:

-(Note*) findById:(Note*)model

{

NSString *path = [self applicationDocumentsDirectoryFile];

if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) { ①

sqlite3_close(db);  ②

NSAssert(NO,@”数据库打开失败。”);

} else {

 

NSString *qsql = @”SELECT cdate,content FROM Note where cdate =?”;

 

sqlite3_stmt *statement;

//预处理过程

if (sqlite3_prepare_v2(db, [qsql UTF8String], -1, &statement, NULL) == SQLITE_OK) { ③

//准备参数

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; ④

[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

NSString *nsdate = [dateFormatter stringFromDate:model.date];

//绑定参数开始

sqlite3_bind_text(statement, 1, [nsdate UTF8String], -1, NULL); ⑤

//执行

if (sqlite3_step(statement) == SQLITE_ROW) { ⑥

char *cdate = (char *) sqlite3_column_text(statement, 0); ⑦

NSString *nscdate = [[NSString alloc] initWithUTF8String: cdate];

 

char *content = (char *) sqlite3_column_text(statement, 1);

NSString * nscontent = [[NSString alloc] initWithUTF8String: content];

Note* note = [[Note alloc] init];

note.date = [dateFormatter dateFromString:nscdate];

note.content = nscontent;

 

sqlite3_finalize(statement);

sqlite3_close(db);

return note;

}

}

 

sqlite3_finalize(statement); ⑧

sqlite3_close(db);  ⑨

 

}

return nil;

}



该方法执行了6个步骤,其中第1个步骤,代码第①行所示,它与创建数库的第1个步骤是一样的,不用再介绍了。

第 2个步骤,代码第③行所示,语句 sqlite3_prepare_v2(db, [qsql UTF8String], -1, &statement, NULL)是预处理 SQL语句,预处理目的是将SQL编译成二进制代码,提高SQL语句执行的速度。sqlite3_prepare_v2函数的第3个参数-1代表全部 sql字符串长度,第4个参数&statement是sqlite3_stmt指针的地址,它是语句对象,通过语句对象可以执行SQL语句,第5 个参数是sql语句没有被执行的部分语句。

第3个步骤,代码第⑤行所示,语句sqlite3_bind_text(statement, 1, [nsdate UTF8String], -1, NULL)是绑定SQL语句参数。在SQL语句中带有问号,这个问号就是要绑定的参数,问号是占位符。

NSString *qsql = @”SELECT cdate,content FROM Note where cdate =?”;

sqlite3_bind_text函数是绑定参数,第1个参数是statement指针,第2个参数为序号(从1开始),第3个参数为字符串值,第4个参数为字符串长度,第5个参数为一个函数指针。

第4个步骤sqlite3_step(statement)执行SQL语句,代码第⑥行所示,sqlite3_step返回int类型,等于SQLITE_ROW说明还要其它的行没有遍历。

第 5个步骤提取字段数据,代码第⑦行所示,使用sqlite3_column_text(statement, 0)函数可以读取字符串类型字段,第2参数 是指定select字段的索引(从0开始)。同样char*转换成为NSString*类型,需要initWithUTF8String:构造方法。读取 字段函数采用与字段类型有关系,SQLite3的类似的常用函数还有:

sqlite3_column_blob()

sqlite3_column_double()

sqlite3_column_int()

sqlite3_column_int64()

sqlite3_column_text()

sqlite3_column_text16()

关于其它的API可以参考http://www.sqlite.org/cintro.html。

第6个步骤是释放资源,创建数据库过程不同,除了使用sqlite3_close函数关闭数据库,代码第⑧行所示,还要使用sqlite3_finalize函数释放语句对象statement代码第⑨行所示。

NoteDAO.m中的查询所有数据方法:

-(NSMutableArray*) findAll

{

NSString *path = [self applicationDocumentsDirectoryFile];

NSMutableArray *listData = [[NSMutableArray alloc] init];

if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) {

sqlite3_close(db);

NSAssert(NO,@”数据库打开失败。”);

} else {

 

NSString *qsql = @”SELECT cdate,content FROM Note”;

 

sqlite3_stmt *statement;

//预处理过程

if (sqlite3_prepare_v2(db, [qsql UTF8String], -1, &statement, NULL) == SQLITE_OK) {

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];

[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

//执行

while (sqlite3_step(statement) == SQLITE_ROW) {

char *cdate = (char *) sqlite3_column_text(statement, 0);

NSString *nscdate = [[NSString alloc] initWithUTF8String: cdate];

 

char *content = (char *) sqlite3_column_text(statement, 1);

NSString * nscontent = [[NSString alloc] initWithUTF8String: content];

Note* note = [[Note alloc] init];

note.date = [dateFormatter dateFromString:nscdate];

note.content = nscontent;

[listData addObject:note];

}

}

 

sqlite3_finalize(statement);

sqlite3_close(db);

 

}

return listData;

}



查询所有数据方法与按照主键查询数据方法类似,区别在于本方法没有查询条件不需要绑定参数。遍历的时候使用while循环语句,不是if语句。

while (sqlite3_step(statement) == SQLITE_ROW) {

… …

}

修改数据 

修改数据包括:insert、update和delete语句。这3个SQL语句都可以带有参数,关于参数的绑定与查询where子句绑定的方式是一样的。执行修改数据步骤如下:

1、使用sqlite3_open函数打开数据库;

2、使用sqlite3_prepare_v2函数预处理SQL语句;

3、使用sqlite3_bind_text函数绑定参数;

4、使用sqlite3_step函数执行SQL语句;

5、使用sqlite3_finalize和sqlite3_close函数释放资源。

修改数据的步骤与查询数据的步骤相比少了一个提取字段数据步骤。下面我们看看代码部分。其它的步骤是一样的。

NoteDAO.m中的插入Note方法:

-(int) create:(Note*)model

{

NSString *path = [self applicationDocumentsDirectoryFile];

if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) { ①

sqlite3_close(db);  ②

NSAssert(NO,@”数据库打开失败。”);

} else {

 

NSString *sqlStr = @”INSERT OR REPLACE INTO note (cdate, content) VALUES (?,?)”;

 

sqlite3_stmt *statement;

//预处理过程

if (sqlite3_prepare_v2(db, [sqlStr UTF8String], -1, &statement, NULL) == SQLITE_OK) { ③

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];

[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

NSString *nsdate = [dateFormatter stringFromDate:model.date];

//绑定参数开始

sqlite3_bind_text(statement, 1, [nsdate UTF8String], -1, NULL);  ④

sqlite3_bind_text(statement, 2, [model.content UTF8String], -1, NULL);

 

//执行插入

if (sqlite3_step(statement) != SQLITE_DONE) { ⑤

NSAssert(NO, @”插入数据失败。”);

}

}

 

sqlite3_finalize(statement);  ⑥

sqlite3_close(db);  ⑦

}

return 0;

}



第⑤行代码sqlite3_step(statement)语句执行插入语句,常量SQLITE_DONE执行完成。

NoteDAO.m中的删除Note方法:

-(int) remove:(Note*)model

{

NSString *path = [self applicationDocumentsDirectoryFile];

if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) {

sqlite3_close(db);

NSAssert(NO,@”数据库打开失败。”);

} else {

 

NSString *sqlStr = @”DELETE  from note where cdate =?”;

 

sqlite3_stmt *statement;

//预处理过程

if (sqlite3_prepare_v2(db, [sqlStr UTF8String], -1, &statement, NULL) == SQLITE_OK) {

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];

[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

NSString *nsdate = [dateFormatter stringFromDate:model.date];

//绑定参数开始

sqlite3_bind_text(statement, 1, [nsdate UTF8String], -1, NULL);

//执行插入

if (sqlite3_step(statement) != SQLITE_DONE) {

NSAssert(NO, @”删除数据失败。”);

}

}

 

sqlite3_finalize(statement);

sqlite3_close(db);

}

return 0;

}

NoteDAO.m中的修改Note方法:

-(int) modify:(Note*)model

{

NSString *path = [self applicationDocumentsDirectoryFile];

if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) {

sqlite3_close(db);

NSAssert(NO,@”数据库打开失败。”);

} else {

 

NSString *sqlStr = @”UPDATE note set content=? where cdate =?”;

 

sqlite3_stmt *statement;

//预处理过程

if (sqlite3_prepare_v2(db, [sqlStr UTF8String], -1, &statement, NULL) == SQLITE_OK) {

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];

[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

NSString *nsdate = [dateFormatter stringFromDate:model.date];

//绑定参数开始

sqlite3_bind_text(statement, 1, [model.content UTF8String], -1, NULL);

sqlite3_bind_text(statement, 2, [nsdate UTF8String], -1, NULL);

//执行插入

if (sqlite3_step(statement) != SQLITE_DONE) {

NSAssert(NO, @”修改数据失败。”);

}

}

 

sqlite3_finalize(statement);

sqlite3_close(db);

}

return 0;

}



分享到:
评论

相关推荐

    vs2017 xamarin使用本地sqlite数据库源码

    10. **数据持久化**:SQLite作为本地数据库,可以实现应用的数据持久化,即使应用关闭,数据也能被保存并下次加载。 通过这个DEMO源码,开发者可以学习到如何在VS2017中配置Xamarin Android项目,集成SQLite数据库...

    iOS关于数据持久化的

    在iOS应用开发中,数据持久化是至关重要的一个环节,它允许应用程序在用户退出或设备重启后仍能保存和恢复数据。本资料主要探讨的是iOS中的数据存储方式,特别是使用FMDB库对SQLite数据库进行封装以及SQL语言的应用...

    ios-数据库.zip

    在iOS开发中,数据持久化是一项至关重要的技术,它使得应用程序可以保存用户的数据并在下次启动时继续使用。在这个“ios-数据库.zip”压缩包中,我们很可能会找到关于如何在iOS应用中实现简单数据存储的示例代码或...

    ios-iOS swift版 sqlite3 详解.zip

    完整的sqlite3封装,包括对data数据类型的存储,版本的升级,以及事务的添加,索引的添加,还有,优化查询速度,增加数据库列属性等等。值得学习以及在项目中使用。github地址是:...

    Flutter持久化存储之数据库存储(sqflite)详解

    数据库存储是我们常用的存储方式之一,对大批量数据有增、删、改、查操作需求时,我们就会想到使用数据库,Flutter中提供了一个sqflite插件供我们用于大量数据执行CRUD操作。本篇我们就来一起学习sqflite的使用。 ...

    iOS开发进阶-完整版

    - **数据持久化存储**: - Core Data框架详解:实体模型设计、数据增删改查操作。 - SQLite数据库:基本操作、查询优化技巧。 - UserDefaults:简单数据类型存储方法。 #### 三、高级主题与实践案例 - **多线程...

    XML-SQLite-Quiz-Demo:(Android) 简单的测验应用程序。 从 XML 解析问题并将它们加载到本地 SQLite 数据库中

    在测验应用中,SQLite数据库用于持久化问题和答案,方便快速检索和显示。创建数据库和表的SQL语句可能如下: ```sql CREATE TABLE Quiz ( id INTEGER PRIMARY KEY AUTOINCREMENT, question TEXT NOT NULL, ...

    ios-PachagingSqlite.zip

    《iOS中的SQLite数据库封装——PachagingSqlite详解》 在iOS应用开发中,数据持久化是必不可少的一部分,它能够确保应用在关闭或重启后仍能保留用户数据。SQLite是一种流行的关系型数据库管理系统,被广泛应用于...

    IOS应用源码之artifice-backend.zip

    3. 数据持久化层:处理本地数据存储,可能包括SQLite数据库、Core Data或者文件系统。 二、网络通信技术 Artifice-Backend可能使用了诸如AFNetworking或Alamofire这样的第三方库进行网络请求。这些库简化了HTTP...

    ios-car-dashboard-master_ios_made_

    8. Core Data或SQLite存储:为了保存用户设置和历史数据,开发者可能会使用Core Data(Apple的持久化框架)或SQLite数据库。 9. 响应式设计:为了适应不同的驾驶环境,如日间和夜间模式,应用可能包含动态颜色管理...

    零基础iOS和Swift开发全套视频

    - Core Data框架介绍:持久化存储方案之一,支持关系型数据模型。 - SQLite数据库使用:轻量级的文件型数据库,适用于小型项目。 - UserDefaults:用于保存简单的配置信息,如用户偏好设置等。 #### 三、实战...

    iOS中数据存储方式详解

    在iOS开发中,数据存储是不可或缺的一部分,它涉及到应用程序如何持久化用户数据、配置信息以及应用状态。本文将深入探讨iOS中的几种主要数据存储方式,包括:偏好设置、文件系统、SQLite数据库、Core Data以及归档...

    斯坦福2011-2012ios教程课件

    - SQLite:轻量级数据库,也可用于iOS应用的数据存储。 - NSUserDefaults:用于存储轻量级的用户偏好设置和状态数据。 4. 网络编程: - NSURLSession:用于处理网络请求,包括HTTP/HTTPS协议,以及下载和上传...

    IOS应用源码——xorna-CodeRockrJam-05292fa.rar

    此外,为了提高用户体验,iOS应用往往需要进行数据持久化,这可能涉及到Core Data或SQLite数据库。Core Data是苹果提供的对象图形管理框架,用于存储和检索应用程序的数据。在源码中,我们可能能看到NSManagedObject...

    IOS 第三方FMDB包

    在iOS应用开发中,数据管理是不可或缺的一部分,尤其是在需要进行本地数据持久化存储时。FMDB就是一款优秀的第三方数据库管理库,它为iOS应用程序提供了SQLite数据库的简单Objective-C封装,使得开发者能够方便、...

    IOS面试题总结,集合了很多培训机构的老师精心整理出来的,绝对给力

    4. **数据持久化** - NSUserDefaults的简单数据存储。 - CoreData框架的应用,用于复杂数据模型管理。 - SQLite数据库的集成和查询操作。 5. **网络编程** - NSURLSession的使用,包括同步和异步请求。 - JSON...

    ios-XHCoreData.zip

    CoreData是苹果提供的一种数据管理框架,用于在iOS和macOS应用中实现数据持久化。它不仅提供了对象关系映射(ORM)的功能,还能帮助开发者处理数据库事务、缓存管理和数据检索等复杂任务。对于初学者来说,理解并...

    iOS-CoreData源码Demo

    6. **Persistent Store Coordinator (PSC)**: PSC协调MOC与持久化存储(如SQLite数据库)之间的通信。 7. **模型(Model)**: 数据模型定义了实体、属性和关系,通常以`.xcdatamodeld`文件形式存在。 ### CoreData...

    IOS应用源码之akosma-fontbrowser-1053a20.zip

    考虑到用户可能需要保存浏览记录或设置,源码中可能会有NSUserDefault、CoreData或SQLite等数据持久化机制的使用,以保存应用程序的状态。 6. **网络请求**: 如果FontBrowser支持在线字体库,那么源码可能涉及...

Global site tag (gtag.js) - Google Analytics