使用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添加。

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;

}

iOS数据持久化-SQLite数据库使用详解的更多相关文章

  1. windows phone 8.1开发SQlite数据库操作详解

    原文出自:http://www.bcmeng.com/windows-phone-sqlite1/ 本文小梦将和大家分享WP8.1中SQlite数据库的基本操作:(最后有整个示例的源码)(希望能通过本 ...

  2. iOS数据持久化之数据库:SQLite和FMDB

    SQLite: SQLite是一款轻量级型的数据库,资源占用少.性能良好和零管理成本,具有零配置(无需安装和管理配置).独立(没有额外依赖).储存在单一磁盘文件中的一个完整的数据库.源码完全的开源.比 ...

  3. IOS 数据存储之 Core Data详解

    Core Date是ios3.0后引入的数据持久化解决方案,它是是苹果官方推荐使用的,不需要借助第三方框架.Core Date实际上是对SQLite的封装,提供了更高级的持久化方式.在对数据库操作时, ...

  4. SQLite数据库数据类型详解

    数据类型 类型 描             述 bit 整型 bit 数据类型是整型,其值只能是0.1或空值.这种数据类型用于存储只有两种可能值的数据,如Yes 或No.True 或Fa lse .O ...

  5. iOS 数据持久化(扩展知识:模糊背景效果和密码保护功能)

    本篇随笔除了介绍 iOS 数据持久化知识之外,还贯穿了以下内容: (1)自定义 TableView,结合 block 从 ViewController 中分离出 View,轻 ViewControll ...

  6. iOS开发笔记-swift实现iOS数据持久化之归档NSKeyedArchiver

    IOS数据持久化的方式分为三种: 属性列表 (plist.NSUserDefaults) 归档 (NSKeyedArchiver) 数据库 (SQLite.Core Data.第三方类库等 归档(又名 ...

  7. 转载 -- iOS数据持久化存储

    作者:@翁呀伟呀 授权本站转载 概论 所谓的持久化,就是将数据保存到硬盘中,使得在应用程序或机器重启后可以继续访问之前保存的数据.在iOS开发中,有很多数据持久化的方案,接下来我将尝试着介绍一下5种方 ...

  8. IOS数据持久化之归档NSKeyedArchiver

    IOS数据持久化的方式分为三种: 属性列表 (自定义的Property List .NSUserDefaults) 归档 (NSKeyedArchiver) 数据库 (SQLite.Core Data ...

  9. iOS数据持久化

    在iOS中,实现数据持久化一般分为4大种: 1.属性列表 2.对象归档 3.SQLite 4.Core Data 一.属性列表 NSUserDefaults类的使用和NSKeyedArchiver有很 ...

随机推荐

  1. 关于android 图像格式问题

    这算是篇总结吧.6月份开始做的一个android上的ar项目结束了.我做的部分是二维码识别和图像识别的预处理.这个项目虽然很累,但是让我学到了很多东西,特别是严格的编码规则,和java代码的效率优化, ...

  2. //判断是否安装Flash插件

    //判断是否安装Flash插件        var swf;        function IE_Flash() {            try {                var swf ...

  3. LFS7.4编译笔记(3)

    在第一部分,我们编译了一个工具链及临时系统,然后在第二部分我们chroot到/mnt/lfs下面,利用临时系统的工具编译了我们最终的LFS系统.不过此时,我们的LFS系统还是不完整的,因为我们还没有安 ...

  4. ios实例开发精品源码文章推荐

    iOS源码:游戏引擎-推箱子游戏 http://www.apkbus.com/android-106392-1-11.html iOS源码:进度条-Colorful ProgressView http ...

  5. Properties 转换成Map

    转自:http://feitianbenyue.iteye.com/blog/1759259 对于Properties 转换成Map 的问题: 第一时间想到的肯定有以下: 1.  迭代出来  再 pu ...

  6. oracle 回车、换行符

    1.回车换行符 chr(10)是换行符,chr(13)是回车, 增加换行符 select ' update ' || table_name ||       ' set VALID_STATE ='' ...

  7. Java_Shell多线程

    #!/bin/bash source ~/.bashrc fun(){ echo "fun is begin.timeNum:$timeNum" local timeNum=$ s ...

  8. SQL性能优化十条经验

    1.查询的模糊匹配 尽量避免在一个复杂查询里面使用 LIKE '%parm1%'—— 红色标识位置的百分号会导致相关列的索引无法使用,最好不要用. 解决办法: 其实只需要对该脚本略做改进,查询速度便会 ...

  9. postgres函数

    1.数据修复最先考虑通过db内做修复,实在不行,在考虑外部应用程序通过jdbc修复. 比如一个场景:profile_image_url与enlarge_image_url都是微博用户信息返回的字段. ...

  10. mysql避免插入重复数据

    我们在进行数据库操作的时候,有时候需要插入不重复的数据.所谓不重复的数据,可以是某个字段不重复,也可以是某几个字段重复.当然我们可以在插入之前先将数据库的数据查询出来,然后与将要插入的数据进行对比,如 ...