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添加。
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数据库使用详解的更多相关文章
- windows phone 8.1开发SQlite数据库操作详解
原文出自:http://www.bcmeng.com/windows-phone-sqlite1/ 本文小梦将和大家分享WP8.1中SQlite数据库的基本操作:(最后有整个示例的源码)(希望能通过本 ...
- iOS数据持久化-SQLite数据库使用详解
使用SQLite数据库 创建数据库 创建数据库过程需要3个步骤: 1.使用sqlite3_open函数打开数据库: 2.使用sqlite3_exec函数执行Create Table语句,创建数据库表: ...
- SQLite数据库数据类型详解
数据类型 类型 描 述 bit 整型 bit 数据类型是整型,其值只能是0.1或空值.这种数据类型用于存储只有两种可能值的数据,如Yes 或No.True 或Fa lse .O ...
- C#操作SQLite方法实例详解
用 C# 访问 SQLite 入门(1) CC++C#SQLiteFirefox 用 C# 访问 SQLite 入门 (1) SQLite 在 VS C# 环境下的开发,网上已经有很多教程.我也是从 ...
- iOS 单元测试之XCTest详解(一)
iOS 单元测试之XCTest详解(一) http://blog.csdn.net/hello_hwc/article/details/46671053 原创blog,转载请注明出处 blog.csd ...
- iOS学习之UINavigationController详解与使用(一)添加UIBarButtonItem
http://blog.csdn.net/totogo2010/article/details/7681879 1.UINavigationController导航控制器如何使用 UINavigati ...
- IOS—UITextFiled控件详解
IOS—UITextFiled控件详解 //初始化textfield并设置位置及大小 UITextField *text = [[UITextField alloc]initWithFrame:CGR ...
- [转]iOS学习之UINavigationController详解与使用(三)ToolBar
转载地址:http://blog.csdn.net/totogo2010/article/details/7682641 iOS学习之UINavigationController详解与使用(二)页面切 ...
- IOS 友盟使用详解
IOS 友盟使用详解 这篇博客将会详细介绍友盟的使用,希望对博友们有所帮助. 首先我们在浏览器上搜索友盟. 在这里我们选择官网这个,进去友盟官网后我们按照下图进行选择. 接下来选择如下图 Next 这 ...
- iOS原生地图开发详解
在上一篇博客中:http://my.oschina.net/u/2340880/blog/414760.对iOS中的定位服务进行了详细的介绍与参数说明,在开发中,地位服务往往与地图框架结合使用,这篇博 ...
随机推荐
- PBR工作流
目标是让substance效果和unity效果一致 分2步: 1.完成1个shader,效果和standard完全一致,抛去不需要的功能 2.使用新的shader,在substance里替代原有的渲染 ...
- Neutron相关资料链接
1.OpenStack Neturon 官方文档: https://docs.openstack.org/mitaka/networking-guide/ 2.Neturon理解系列文章: http: ...
- MongoDB-1:安装和配置
一.简介 MongoDB一种非关系型数据库(NoSql),是一种强大.灵活.可扩展的数据存储方式,因为MongoDB是文档模型,自由灵活很高,可以让你在开发过程中畅顺无比,对于大数据量.高并发.弱事务 ...
- 我的Android进阶之旅】GitHub 上排名前 100 的 Android 开源库进行简单的介绍
GitHub Android Libraries Top 100 简介 本文转载于:https://github.com/Freelander/Android_Data/blob/master/And ...
- 最大熵模型(Maximum Entropy Models)具体分析
因为本篇文章公式较多,csdn博客不同意复制公式,假设将公式一一保存为图片在上传太繁琐了,就用word排好版后整页转为图片传上来了.如有错误之处.欢迎指正.
- Android ViewGroup onInterceptTouchEvent
public boolean onInterceptTouchEvent (MotionEvent ev) Implement this method to intercept all touch s ...
- Spring的IoC模式
1.依赖 依赖就是有联系,有地方使用到它就是有依赖它,一个系统不可能完全避免依赖.如果你的一个类或者模块在项目中没有用到它,恭喜你,可以从项目中剔除它或者排除它了,因为没有一个地方会依赖它.下面看一个 ...
- PAT 1085 Perfect Sequence[难]
1085 Perfect Sequence (25 分) Given a sequence of positive integers and another positive integer p. T ...
- iOS学习之二维码扫描
这几天刚好将本人高仿新浪微博的事情进行一个阶段性的tag,在此也将这个项目在实现二维码扫描这个功能来做一个简要的记录.关于高仿新浪微博的源代码,本人已经将全部代码托管到github,地址在这里.欢迎大 ...
- Android 属性自定义及使用获取浅析
一.概述 相信你已经知道,Android 可使用 XML 标签语言进行界面的定义.每个标签中有一个一个的属性,这些属性有相应的属性值.例如: <cn.neillee.composedmenu.R ...