一、数据库

在项目开发中,通常都需要对数据进行离线缓存的处理,如新闻数据的离线缓存等。离线缓存一般都是把数据保存到项目的沙盒中。有以下几种方式:

  1. 归档:NSKeyedArchiver
  2. 偏好设置:NSUserDefaults
  3. plist存储:writeToFile

上述的使用可以参考iOS学习笔记15-序列化、偏好设置和归档,但上述三种方法都有一个致命的缺点,那就是都无法存储大批量的数据,有性能的问题,在这个时候就是使用数据库的时候。

数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,用于存储管理大量的数据,可以高效的存储大批量数据,也可以高效的读取大批量数据,功能强大。

数据库的存储结构和excel很像,以表(table)为单位 。表由多个字段(列、属性、column)组成,表里面的每一行数据称为记录,但又不是简单的表格,还有表与表之间的关系,也就是现在主流的关系型数据库。

二、SQLite介绍

SQLite是一款轻型的嵌入式数据库,安卓和iOS开发使用的都是SQLite数据库。
它的特点:

  1. 它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。
  2. 它的处理速度比MySQL、PostgreSQL这两款著名的数据库都还快。
  3. 它是C语言框架的,跨平台性强。

我们现在已经到了SQLite3时代了,后面的3是版本,现在我们就开始来使用它吧。

三、SQLite3的使用

一般常用的数据库操作有:【本章就以这5个步骤进行讲解】
  1. 创建数据库
  2. 创建表
  3. 向表插入数据
  4. 从表中读取数据
  5. 关闭数据库

要在iOS中使用SQLite3,需要在Xcode导入libsqlite3的库

上面两个其中一个都可以,然后我们还需要在项目中添加头文件和定义一个数据库句柄,这个数据库句柄控制数据库的所有操作。

1. 打开数据库

使用的C语言函数如下:
/* 打开数据库 */
int sqlite3_open(
const char *filename, /* 数据库路径(UTF-8) */
sqlite3 **pDb /* 返回的数据库句柄 */
);
下面是实例:
/* 打开数据库 */
- (void)openDatabase:(NSString *)dbname
{
//生成沙盒文件路径
NSString *directory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) lastObject];
NSString *filePath = [directory stringByAppendingPathComponent:dbname];
//打开数据库,如果数据库存在直接打开,如果数据库不存在,创建并打开
int result = sqlite3_open(filePath.UTF8String, &_database);
if (result == SQLITE_OK) {
NSLog(@"Open Database Success");
} else {
NSLog(@"Open Database Fail");
}
}

2. 执行没有返回值得SQL语句

使用的C语言函数:
/* 执行没有返回的SQL语句 */
int sqlite3_exec(
sqlite3 *db, /* 数据库句柄 */
const char *sql, /* SQL语句(UTF-8) */
int (*callback)(void*,int,char**,char**), /* 回调的C函数指针 */
void *arg, /* 回调函数的第一个参数 */
char **errmsg /* 返回的错误信息 */
);
使用实例:
/* 执行没有返回值的SQL语句 */
- (void)executeNonQuery:(NSString *)sql
{
if (!_database) {
return;
}
char *error;
//执行没有返回值的SQL语句
int result = sqlite3_exec(_database, sql.UTF8String, NULL, NULL, &error);
if (result == SQLITE_OK) {
NSLog(@"Execute SQL Query Success");
} else {
NSLog(@"Execute SQL Query Fail error : %s",error);
}
}

3.执行有返回值的SQL语句

使用的C语言函数:
/* 执行有返回结果的SQL语句 */
int sqlite3_prepare_v2(
sqlite3 *db, /* 数据库句柄 */
const char *zSql, /* SQL语句(UTF-8) */
int nByte, /* SQL语句最大长度,-1表示SQL支持的最大长度 */
sqlite3_stmt **ppStmt, /* 返回的查询结果 */
const char **pzTail /* 返回的失败信息*/
);
既然有返回结果,怎么处理返回结果,也有一些C语言函数:
#pragma mark - 定位记录的方法
/* 在查询结果中定位到一条记录 */
int sqlite3_step(sqlite3_stmt *stmt);
/* 获取当前定位记录的字段名称数目 */
int sqlite3_column_count(sqlite3_stmt *stmt);
/* 获取当前定位记录的第几个字段名称 */
const char * sqlite3_column_name(sqlite3_stmt *stmt, int iCol);
# pragma mark - 获取字段值的方法
/* 获取二进制数据 */
const void * sqlite3_column_blob(sqlite3_stmt *stmt, int iCol);
/* 获取浮点型数据 */
double sqlite3_column_double(sqlite3_stmt *stmt, int iCol);
/* 获取整数数据 */
int sqlite3_column_int(sqlite3_stmt *stmt, int iCol);
/* 获取文本数据 */
const unsigned char * sqlite3_column_text(sqlite3_stmt *stmt, int iCol);
使用实例:
/* 执行有返回值的SQL语句 */
- (NSArray *)executeQuery:(NSString *)sql
{
if (!_database) {
return nil;
}
NSMutableArray *array = [NSMutableArray array];
sqlite3_stmt *stmt; //保存查询结果
//执行SQL语句,返回结果保存在stmt中
int result = sqlite3_prepare_v2(_database, sql.UTF8String, -1, &stmt, NULL);
if (result == SQLITE_OK) {
//每次从stmt中获取一条记录,成功返回SQLITE_ROW,直到全部获取完成,就会返回SQLITE_DONE
while( SQLITE_ROW == sqlite3_step(stmt)) {
//获取一条记录有多少列
int columnCount = sqlite3_column_count(stmt);
//保存一条记录为一个字典
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
for (int i = 0; i < columnCount; i++) {
//获取第i列的字段名称
const char *name = sqlite3_column_name(stmt, i);
//获取第i列的字段值
const unsigned char *value = sqlite3_column_text(stmt, i);
//保存进字典
NSString *nameStr = [NSString stringWithUTF8String:name];
NSString *valueStr = [NSString stringWithUTF8String:(const char *)value];
dict[nameStr] = valueStr;
}
[array addObject:dict];//添加当前记录的字典存储
}
sqlite3_finalize(stmt);//stmt需要手动释放内存
stmt = NULL;
NSLog(@"Query Stmt Success");
return array;
}
NSLog(@"Query Stmt Fail");
return nil;
}

4. 关闭数据库

使用的C语言函数:
/* 关闭数据库 */
int sqlite3_close(sqlite3 *db);
使用实例:
/* 关闭数据库 */
- (void)closeDatabase
{
//关闭数据库
int result = sqlite3_close(_database);
if (result == SQLITE_OK) {
NSLog(@"Close Database Success");
_database = NULL;
} else {
NSLog(@"Close Database Fail");
}
}

四、SQLite结合SQL语句

除了使用libsqlite库里的C语言函数还无法完成对数据库操作,还需要使用到SQL语句,就是一门控制数据库的语言【一个大知识】。

这里就简单列出一些常用的SQL语句:
  1. 创建表:
    create table 表名称(字段1,字段2,……,字段n,[表级约束])[TYPE=表类型];
  2. 插入记录:
    insert into 表名(字段1,……,字段n) values (值1,……,值n);
  3. 删除记录:
    delete from 表名 where 条件表达式;
  4. 修改记录:
    update 表名 set 字段名1=值1,……,字段名n=值n where 条件表达式;
  5. 查看记录:
    select 字段1,……,字段n from 表名 where 条件表达式;
下面是结合SQL语句完成数据库操作,使用到的是上面定义的方法:
/* 结合SQL语句,操作数据库 */
- (void)sqlite3Test{
//打开SQlite数据库
[self openDatabase:@"sqlite3_database.db"];
//在数据库中创建表
[self executeNonQuery:@"create table mytable(num varchar(7),name varchar(7),sex char(1),primary key(num));"];
//在表中插入记录
[self executeNonQuery:@"insert into mytable(num,name,sex) values (0,'liuting','m');"];
[self executeNonQuery:@"insert into mytable(num,name,sex) values (1,'zhangsan','f');"];
[self executeNonQuery:@"insert into mytable(num,name,sex) values (2,'lisi','m');"];
[self executeNonQuery:@"insert into mytable(num,name,sex) values (3,'wangwu','f');"];
[self executeNonQuery:@"insert into mytable(num,name,sex) values (4,'xiaoming','m');"];
//读取数据库的表中数据
NSArray* result = [self executeQuery:@"select num,name,sex from mytable;"];
if (result) {
for (NSDictionary *row in result) {
NSString *num = row[@"num"];
NSString *name = row[@"name"];
NSString *sex = row[@"sex"];
NSLog(@"Read Database : num=%@, name=%@, sex=%@",num,name,sex);
}
}
[self closeDatabase];
}
/* 修改一下,把原来存在的数据库文件删除掉,再创建并打开数据库 */
- (void)openDatabase:(NSString *)dbname
{
//生成沙盒文件路径
NSString *directory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) lastObject];
NSString *filePath = [directory stringByAppendingPathComponent:dbname];
//判断该文件在不在
NSFileManager *manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath:filePath]){
//文件存在,就删除掉
[manager removeItemAtPath:filePath error:NULL];
}
//打开数据库,保持sqlite3数据库对象_database,返回值判别是否打开成功
int result = sqlite3_open(filePath.UTF8String, &_database);
if (result == SQLITE_OK) {
NSLog(@"Open Database Success");
} else {
NSLog(@"Open Database Fail");
}
}

如果你C语言基础比较好的话,是不是感到使用起来也没那么困难,但这样的使用缺少一些面向对象的思想,我们还是会有点不习惯,没关系,下一节我就会讲SQLite的一个轻量级封装第三方开源库FMDB,使得操作SQLite数据库变得方便,敬请期待!

iOS学习笔记16-数据库SQLite的更多相关文章

  1. Python学习笔记 使用数据库SQlite Mysql

    SQLite是一种嵌入式数据库,它的数据库就是一个文件.由于SQLite本身是C写的,而且体积很小,所以,经常被集成到各种应用当中, 甚至在IOS和Android的APP中都可以集成 Python就内 ...

  2. Laravel5.1学习笔记16 数据库2 查询构造器(这个不用看,不如用EloquentORM)

    Introduction Retrieving Results Aggregates Selects Joins Unions Where Clauses Advanced Where Clauses ...

  3. golang学习笔记16 beego orm 数据库操作

    golang学习笔记16 beego orm 数据库操作 beego ORM 是一个强大的 Go 语言 ORM 框架.她的灵感主要来自 Django ORM 和 SQLAlchemy. 目前该框架仍处 ...

  4. SQL反模式学习笔记16 使用随机数排序

    目标:随机排序,使用高效的SQL语句查询获取随机数据样本. 反模式:使用RAND()随机函数 SELECT * FROM Employees AS e ORDER BY RAND() Limit 1 ...

  5. IOS学习笔记48--一些常见的IOS知识点+面试题

      IOS学习笔记48--一些常见的IOS知识点+面试题   1.堆和栈什么区别? 答:管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制:对于堆来说,释放工作由程序员控制,容易产生memor ...

  6. iOS学习笔记17-FMDB

    上一节我已经介绍了SQLite的简单使用,不了解的可以提前去看一下iOS学习笔记16-数据库SQLite,这节我们来讲下FMDB. 一.FMDB介绍 FMDB是一种第三方的开源库,FMDB就是对SQL ...

  7. iOS学习笔记17-FMDB你好!

    上一节我已经介绍了SQLite的简单使用,不了解的可以提前去看一下iOS学习笔记16-数据库SQLite,这节我们来讲下FMDB. 一.FMDB介绍 FMDB是一种第三方的开源库,FMDB就是对SQL ...

  8. iOS学习笔记-精华整理

    iOS学习笔记总结整理 一.内存管理情况 1- autorelease,当用户的代码在持续运行时,自动释放池是不会被销毁的,这段时间内用户可以安全地使用自动释放的对象.当用户的代码运行告一段 落,开始 ...

  9. MongoDB学习笔记:MongoDB 数据库的命名、设计规范

    MongoDB学习笔记:MongoDB 数据库的命名.设计规范     第一部分,我们先说命名规范. 文档 设计约束 UTF-8 字符 不能包含 \0 字符(空字符),这个字符标识建的结尾 . 和 $ ...

随机推荐

  1. 声明已被否决 VS C++

    error C4996声明已被否决,不止一次碰到这个问题,在这里必须mark一下! 尝试这个1.Project Properties > Configuration Properties > ...

  2. Android Studio项目上传到Jcenter

    一.将你要发布的moudle的build.gradle中添加代码,gradle的最后添加 PUBLISH_GROUP_ID = 'com.zzti.fengyongge' PUBLISH_ARTIFA ...

  3. spring 配置多个properties

    复制多份,保证有效的配置文件,属性时true就行 <bean class="org.springframework.beans.factory.config.PropertyPlace ...

  4. COGS 930. [河南省队2012] 找第k小的数

    题目描述 看到很短的题目会让人心情愉悦,所以给出一个长度为N的序列A1,A2,A3,...,AN, 现在有M个询问,每个询问都是Ai...Aj中第k小的数等于多少. 输入格式 第一行两个正整数N,M. ...

  5. codevs 1606 台阶

    时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题目描述 Description 话说某牛家门外有一台阶,这台阶可能会很高(总层数<=1000000). 这 ...

  6. Linux OpenGL 实践篇-12-procedural-texturing

    程序式纹理 简单的来说程序式纹理就是用数学公式描述物体表面的纹路 .而实现这个过程的着色器我们称之为程序纹理着色器,通常在这类着色器中我们能使用的输入信息也就是顶点坐标和纹理坐标. 程序式纹理的优点 ...

  7. Swift REPL入门介绍

    Xcode 6.1 引入了一个新特性用来辅助Swift开发,即Read Eval Print Loop(“读取-求值-输出”循环,简称REPL).熟悉解释型语言的开发者将会对这个命令行环境感到舒适,而 ...

  8. Gym - 101291C (很有意思的最短路)

    题意: 给出一张地图和机器人还有出口的位置,地图上面有障碍.然后给出UDLR上下左右四种指令,遇到障碍物或者越界的指令会忽略,剩下的继续执行. 只要到达出口就算找到出口,然后给你一串指令,让你修改指令 ...

  9. Java Web应用中获取用户请求相关信息,如:IP地址、操作系统、浏览器等信息

    引入jar包 <dependency> <groupId>eu.bitwalker</groupId> <artifactId>UserAgentUti ...

  10. MySQL 实时监控日志

    简单的梳理一下为什么要写这边文章,主要是学了ORM之后,发现通过ORM插入数据真的很方便,但是通过ORM生成的SQL语句又是怎么写的呢,百思不得姐.于是就找到了这个办法 首先查看一下查看MySQL 日 ...