iOS系统自带Core Data来进行持久化处理,而且Core Data可以使用图形化界面来创建对象,但是Core Data不是关系型数据库,对于Core Data来说比较擅长管理在设备上创建的数据持久化存储用户创建的对象,但是要处理大量的数据时就应该优先选择SQL关系型数据库来存储这些数据。

Core Data在后台也是使用SQLite来存储数据的,但是开发人员不能直接访问这些数据,只能通过Core Data提供的API来操作,如果一旦人为的通过SQLite修改这些数据那么使用Core Data再次访问这些数据时就会发生错误。

SQLite库

SQLite是使用C语言写的开源库,实现了一个自包含的SQL关系型数据库引擎,可以使用SQLite存储操作大量的数据,作为关系型数据库我们可以在一个数据库中建立多张相关联的表来解决大量数据重复的问题。而且SQLite库也针对移动设备上的使用进行了优化。

因为SQLite的接口使用C写的,而且Objective-CC的超集所以可以直接在项目中使用SQLite

设计一个数据库

开始之前首先要想到需要存什么数据,然后怎么设计这个数据库。

首先我们设计一个数据库用来存储人员信息如下:

id name age email region
1 jhon 20 jhon@mail beijing
2 peter 20 peter@mail shanghai
3 july 20 july@mail beijing
4 elev 20 elev@mail shenzhen
5 ribet 20 ribet@mail beijing

上面是所有的人员信息,实际可能比这个多很多。但是我们发现region这一行中有很多的数据重复出现。很多人可能来自同一个地方,为了避免这种情况我们应该再重新创建一张表来单独存储region这列的信息然后在这个表中引用region表中的信息。当然我们还可以在region表中添加更多的信息比如详细地址。现在创建两张表peopleregion如下所示

  • people表
id name age email region
1 jhon 20 jhon@mail 1
2 peter 20 peter@mail 2
3 july 20 july@mail 1
4 elev 20 elev@mail 3
5 ribet 20 ribet@mail 1
  • region表
regionid regioninfo address
1 beijing fengtai
2 shanghai jingan
3 shenzhen futian

使用SQLite创建数据库

为了熟悉SQLite语句,打开shell使用SQLite命令行来创建一个数据库

  • 打开创建数据库

    打开shell切换到指定目录输入
sqlite3 database.db

这行命令是启动sqlite命令行并且创建新的数据库database.db并附加该数据到命令行

此时已经进入sqlite命令行通过输入.help可以显示可以使用哪些命令,通过输入.databases来查看当前有哪些数据库附加到当前的命令行工具中。输入.quit.exit退出当前命令行工具

  • 创建表
create table "main"."people" ("id" integer primary key autoincrement not null, "name" text,"age" integer,"email" text,"region" integer);

这条命令是创建一个people的表,并且将id字段设为primary key主键将其指定为一个autoincrement自动增长的字段。表示不用提供id的值数据库将自动生成。后面的表示该张表中所含有的字段。

因为要设计两张表所以还需要创建region

create table "main"."region" ("regionid" integer primary key autoincrement not null, "regioninfo" text,"address" text not null);
  • 添加数据

    此时已经成功创建了两张表我们要添加数据进去
insert into "main"."people" ("name","age","email","region") values ('jhon','20','jhon@mail','1');

这样成功往people表成功的插入了一条数据。这样写效率比较低。每次只能插入一条数据不要担心SQLite支持将文件直接导入数据库中。可以是普通的文件文件也可以是excel文件。下面我们创建一个people.txt文件格式如下:

1   jhon    20  jhon@mail   1
2 peter 20 peter@mail 2
3 july 20 july@mail 1
4 elev 20 elev@mail 3
5 ribet 20 ribet@mail 1

注意每个字段之间的空隙是用制表符\t来分割的,也就是创建文件是每个字段用tab键进行分割。字段的顺序必须和表中的顺序相同然后将people.txt文件导入people表中

.separator "\t"

根据\t来分割字段,然后接着输入

.import "people.txt" people

导入people.txt文件到people表中此时会提示如下错误信息

people.txt:1: INSERT failed: UNIQUE constraint failed: people.id

不用担心这个意思是说已经存在了一个id为1的数据所以这条数据插入失败,是因为我们之前手动了插入了一条数据。可以通过以下指令来查插入的数据

select * from people;

然后用同样的方法创建一个region.txt的文件并将其导入region表中。

注意

使用SQLite命令行可能会出现...>这表示指令输入错误,按ctrl+d即可退出

  • 查询数据上面已经添加完数据通过select指令可以查询这些数据
select * from people;

查询popple表中的所有数据

链接表数据

select name,regioninfo from people,region where people.region=region.regionid;

输出结果

jhon    beijing
peter shanghai
july beijing
elev shenzhen
ribet beijing

peopleregion表中查找nameregioninfo字段并且只查询people.region=region.regionid相匹配的结果,如果没有这个条件那么将出现5*3=15条数据

如果要查找某个地区的人使用where来筛选条件

select name,regioninfo from people,region where people.region=region.regionid and region.regioninfo="beijing";

输出结果

jhon    beijing
july beijing
ribet beijing

iOS中SQLite的使用

开始之前应该在项目中引用SQLite库。TARGETS->General->Linked Frameworks and Libraries如下图所示

将之前创建好的database.db文件导入项目中,并引入sqlite3.h头文件

#import <sqlite3.h>

使用SQLite需要一下几个步骤

  • 声明类变量sqlite3来保存对数据库的引用
  • 使用sqlite3_open打开数据库
  • 创建SQLite语句
  • 创建SQLite语句对象sqlite3_stmt
  • 准备SQLite语句sqlite3_prepare_v2
  • 开始遍历结果sqlite3_step

初始化打开数据库

sqlite3 * database;
-(void)initDatabase
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"database" ofType:@"db"];
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK) {
NSLog(@"open database");
}
else{
sqlite3_close(database);
NSLog(@"error %s",sqlite3_errmsg(database));
}
}

打开数据库如果返回的状态码不是SQLITE_OK那么打开失败关闭数据库并且输出错误信息

查询数据

-(void)operateDatabase
{
const char * sql = "select name,regioninfo from people,region where people.region=region.regionid";
sqlite3_stmt *statement; //创建sql语句对象
int sqlResult = sqlite3_prepare_v2(database, sql, -1, &statement, NULL); //准备sql语句
if ( sqlResult== SQLITE_OK) //是否准备结束
{
while (sqlite3_step(statement) == SQLITE_ROW) //开始遍历查询结果
{
NSLog(@"name %s, region %s",sqlite3_column_text(statement, 0),sqlite3_column_text(statement, 1));
}
}
}

输出结果:

name jhon, region beijing
name peter, region shanghai
name july, region beijing
name elev, region shenzhen
name ribet, region beijing

sqlite3_prepare_v2的参数第一个是数据库连接,第二个是sql语句,第三个是这个语句的长度传入-1表示地道第一个null终止符为止,第四个是返回一个语句对象,第五个是返回一个指向该sql语句的第一个字节的指针。

sqlite3_prepare_v2返回状态码SQLITE_OK时开始遍历结果。

sqlite3_step用来遍历结果如果返回为SQLITE_ROW表示下一行准备结束可以开始查询。所以此处用一个while来便利所以查询的结果

遍历的过程中要取到结果通过一下的函数获取遍历结果

SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt*, int iCol);
SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt*, int iCol);
SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt*, int iCol);
SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt*, int iCol);
SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt*, int iCol);
SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt*, int iCol);
SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt*, int iCol);
SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt*, int iCol);
SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int iCol);

上面是所支持的结果类型,第一个参数为sql语句对象,第二个为获取哪一列的信息。

参数化查询

上面的情况每次sql语句都写死了,如果想要改变某个条件就需要重新写一条语句,幸好sqlite支持参数化查询,每次只需要更改查询条件就可以而不用更改整条sql语句,如果现在只想查询北京地区的人口信息使用参数化查询如下:

-(void)operateDatabase
{
const char * sql = "select name,regioninfo from people,region where people.region=region.regionid and regioninfo=?";
sqlite3_stmt *statement; //创建sql语句对象
int sqlResult = sqlite3_prepare_v2(database, sql, -1, &statement, NULL); //准备sql语句 sqlite3_bind_text(statement, 1, "beijing", -1,SQLITE_TRANSIENT); //绑定参数 if ( sqlResult== SQLITE_OK) //是否准备结束
{
while (sqlite3_step(statement) == SQLITE_ROW) //开始遍历查询结果
{
NSLog(@"name %s, region %s",sqlite3_column_text(statement, 0),sqlite3_column_text(statement, 1));
}
}
}

输出结果:

name jhon, regionbeijing
name july, regionbeijing
name ribet, regionbeijing

可见需要更改的条件sql中用?来代替,然后用sqlite3_bind_text函数来绑定参数。根据类型不同绑定的函数也不同

SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,void(*)(void*));
SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt*, int, double);
SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt*, int, int);
SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt*, int);
SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,void(*)(void*), unsigned char encoding);
SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);

上面列出了所有支持绑定类型的函数。

结束

本篇只是列出了SQLite常用的基础方法,实际开发中数据库可能要比这复杂许多,而且还要考虑数据竞争线程安全的问题。具体还是要自己在开发中实践。

iOS开发数据库SQLite的使用的更多相关文章

  1. iOS开发数据库篇—SQLite简单介绍

    iOS开发数据库篇—SQLite简单介绍 一.离线缓存 在项目开发中,通常都需要对数据进行离线缓存的处理,如新闻数据的离线缓存等. 说明:离线缓存一般都是把数据保存到项目的沙盒中.有以下几种方式 (1 ...

  2. iOS开发数据库篇—SQLite的应用

    iOS开发数据库篇—SQLite的应用 一.简单说明 在iOS中使用SQLite3,首先要添加库文件libsqlite3.dylib和导入主头文件. 导入头文件,可以使用库中的函数(是纯C语言的) 二 ...

  3. IOS开发数据库篇—SQLite模糊查询

    IOS开发数据库篇—SQLite模糊查询 一.示例 说明:本文简单示例了SQLite的模糊查询 1.新建一个继承自NSObject的模型 该类中的代码: // // YYPerson.h // 03- ...

  4. iOS开发数据库篇—SQLite常用的函数

    iOS开发数据库篇—SQLite常用的函数 一.简单说明 1.打开数据库 int sqlite3_open( const char *filename,   // 数据库的文件路径 sqlite3 * ...

  5. 【转】 iOS开发数据库篇—SQLite简单介绍

    开始学SQLite啦, 原文: http://www.cnblogs.com/wendingding/p/3868893.html iOS开发数据库篇—SQLite简单介绍 一.离线缓存 在项目开发中 ...

  6. iOS开发数据库篇—SQL

    iOS开发数据库篇—SQL 一.SQL语句 如果要在程序运行过程中操作数据库中的数据,那得先学会使用SQL语句 1.什么是SQL SQL(structured query language):结构化查 ...

  7. iOS开发数据库篇—FMDB简单介绍

    iOS开发数据库篇—FMDB简单介绍 一.简单说明 1.什么是FMDB FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API 2.FMDB的优点 使用起来 ...

  8. iOS开发数据库篇—FMDB数据库队列

    iOS开发数据库篇—FMDB数据库队列 一.代码示例 1.需要先导入FMDB框架和头文件,由于该框架依赖于libsqlite库,所以还应该导入该库. 2.代码如下: // // YYViewContr ...

  9. iOS开发 数据库FMDB

    iOS开发  数据库FMDB 1.简介 需求作用: 如果需要保存大量的结构较为复杂的数据时候, 使用数据库, 例如交规考试项目 常用的数据库: (1)Microsoft SQL Server 2000 ...

随机推荐

  1. 图片轮播的JS写法,通用涉及多个轮播

    本代码是借鉴大神的代码分析理解后,自己改写的!有不足指出希望给为大神指点. 核心只有一个JS,里面包含了css样式. 展示效果图:

  2. VBA中方法的函数式调用和过程式调用的差别

    因见到有人求助批量设置工作簿中的超链接,尝试写了一段代码: Sub AddHyperlinks() Dim strName As String, source As String, target As ...

  3. jsp利用cookie记住用户名,下次登录时显示在文本框中(仅仅一个Cookie就整了将近三个小时,⊙﹏⊙b汗)

    <%@page import="java.net.URLDecoder"%> <%@page import="sun.security.util.Len ...

  4. JAVA帮助文档全系列 JDK1.5 JDK1.6 JDK1.7 官方中英完整版下载

    JAVA帮助文档全系列 JDK1.5 JDK1.6 JDK1.7 官方中英完整版下载JDK(Java Development Kit,Java开发包,Java开发工具)是一个写Java的applet和 ...

  5. Metasploit基础命令

    msf > show exploits 列Metasploip的所有可用的渗透测试框架.在MSF终端中可以针对渗透测试中发现的安全漏洞来实施相应的渗透攻击. msf > show auxi ...

  6. POJ 1142 Smith Numbers(史密斯数)

    Description 题目描述 While skimming his phone directory in 1982, Albert Wilansky, a mathematician of Leh ...

  7. 3----lua的数据转换及运算符

    lua的基本数据类型转换 转换成字符串 tostring( ... ) 可以将布尔类型和数字类型的值转换为字符串类型的值 local num=1; print(type(num)) newNum = ...

  8. Java多线程同步问题的探究

    一.线程的先来后到——问题的提出:为什么要有多线程同步?Java多线程同步的机制是什么? http://www.blogjava.net/zhangwei217245/archive/2010/03/ ...

  9. 表单美化-原生javascript和jQuery多选按钮(兼容IE6)

    前些天我们讲了下单选按钮的美化今天来做表单元素多选按钮的美化.我们的想法是:利用多选按钮是否被选中和是否不给选择的特性来为按钮的父元素添加对应的样式,就是说用什么的样式是由按钮的状态来决定. 用到的图 ...

  10. Oracle冷备份及其恢复

    一. 冷备份的概念 冷备份是指在数据库关闭状态下所做的物理拷贝,也称脱机备份. 适合于非归档模式下的备份,而且也只能采用这种方式备份. 二. 需要备份的文件 必须备份的文件: 数据文件和控制文件 可以 ...