Objective-C访问SQLite
数据库的相关知识我就不去说明了,毕竟只要会sql语言的人就大家都一样。
本案例是在Xcode7.2环境下创建的single view application进行演示操作。
首先第一点,为什么要使用sqlite3?
在iOS的编程中,毫无疑问接触最多的就是界面的代码编排和设计,数据的解析与放置,算法的各种挠头问题。。。 在数据的解析与放置这一块,就会涉及到数据库缓存的操作,我们都知道,iOS手机编程是在手机端运行的,你不能老是去服务器端读取数据啊,好,就算你不烦,手机也跑的起来,流量不要过啊,对于手机控或者应用使用者来说,流量就是生命,而且,如果总是去服务器端读取数据,对手机的运行速度也会有影响,毕竟有一个网络传输的过程,所以,为了让用户有一个更好的体验,一般建议的做法是,将服务器的数据进行下载,然后通过数据库缓存起来,这样就不用每次每次的去请求服务器数据了,如果在数据库中有的数据,直接可以通过数据库查询得到,而省去了一次甚至多次的服务器请求操作。而sqlite3就是提供了一种C语言的访问数据库的形式。之后我们的代码会看到,其实sqlite3的语法可能比较难以理解,不过,我也会给大家来进行介绍的。
那么第二点,使用sqlite3的好处是什么?
使用sqlite3的好处么,除开语法的各种蛋疼之外,访问的速度还是会比FMDB快一些的。而且,随着一步步的汇总和总结,你可以清晰的知道每一句sqlite3的语句的作用,而不是使用封装好了的语句,只要用就可以了,但是不知道是为什么。我个人觉得,学习学习吧,还是要知其然,亦知其所以然这样才能学的踏实。
第一步,引入 libsqlite3.tbd 静态库
第二步,在要使用 SQLite 的地方导入库主头文件 #import <sqlite3.h>
第三步,创建sqlite数据库文件
* sqlite3提供的是一种访问操纵数据库的形式,那么,如果想要使用sqlite3来访问操纵数据库,首先我们得先有个数据库,下面就是使用代码生成一个数据库文件。
// SQLite文件名称 static NSString * const fileName = @"SQLite.sqlite"; // 得到数据库文件地址,这是一个拼接的地址字符串,是沙盒路径下面的shop.sqlite文件 // 这个文件名可以随便取名字,后缀最好是db啊或者sqlite这种,用来表示这是一个数据库文件 NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:fileName];
打开数据库连接,如果有就打开,没有就重新创建连接。
* sqlite3_open是我们接触到的第一条sqlite3语句,它的作用时打开数据库连接,如果有数据库文件就打开它,没有就重新创建数据库,这个方法有一个枚举的返回值表示是否正常打开了数据库,我用int的变量status去接收了这个值,后面会进行判断。
* sqlite3_open有两个参数,第一个参数是数据库文件的路径,第二个参数是一个数据库的引用,即一个sqlite3 *类型的引用;
* filePath.UTF8String: filePath本身是oc的字符串类型,但是sqlite3_open要求传递的是C类型的字符串,所以,使用UTF8String将oc的字符串类型转换为C类型的字符串
@interface ViewController () { sqlite3 *_sqlite; } @end // 打开数据库连接,如果有就打开,没有就重新创建连接 NSInteger state = sqlite3_open(filePath.UTF8String, &_sqlite); // 枚举值SQLITE_OK代表成功的状态 if (state == SQLITE_OK) NSLog(@"----- 打开数据库成功 -----"); else NSLog(@"----- 打开数据库失败 -----");
第四步,创建数据库表
* 当我们打开了数据库连接的时候,表示在程序的沙盒路径下已经创建了一个 SQLite.sqlite 的数据库文件,而这个数据库里现在什么东西都没有,我们需要创建一张数据库表来存放数据。
* sqlite3_exec 是我们接触到的第二个sqlite3语句,这个语句用于执行除了查询语句以外的其他语句.
它有一个枚举类型的返回值,和 sqlite3_open 返回的枚举值一致,这里我并没有使用变量保存,因为我有其他形式来获得创建表是否成功。
* sqlite3_exec 需要传递5个参数,第一个参数是数据库引用即 sqlite3 *_shop,第二个参数是要执行的sql语句,
第三个参数是执行完sql语句后要执行的函数,第四个参数是执行完sql语句后要执行的函数的参数,第五个参数是执行完sql语句后的报错信息。
// 创表语句,IF NOT EXISTS防止创建重复的表,AUTOINCREMENT是自动增长关键字,real是数字类型 const char *sql = "CREATE TABLE IF NOT EXISTS t_SQLite(id integer PRIMARY KEY AUTOINCREMENT, name text NOT NULL, price real)"; //保存错误信息的变量 char *errorMessage = NULL; sqlite3_exec(_sqlite, sql, NULL, NULL, &errorMessage); // 如果存在报错信息,代表语句执行失败,比判断枚举值要更简单一些 if (errorMessage) NSLog(@"----- 创建表失败 -> errorMessage: %s -----", errorMessage); else NSLog(@"----- 创建表成功 -----");
第五步,数据表操作
所谓的数据表操作即是对数据表中数据的增删改,也是最经常会使用到的功能。即执行insert, update, delete语句。
(1)增
* 注:这里我在 Main.storyboard 里面拖了两个输入框(UITextField)和一个按钮(UIButton),并建立关联
@interface ViewController () { sqlite3 *_sqlite; } @property (weak, nonatomic) IBOutlet UITextField *nameField; @property (weak, nonatomic) IBOutlet UITextField *priceField; @end #pragma mark 增 - (IBAction)addDataEvent:(UIButton *)sender { NSString *name = [self.nameField.text stringByReplacingOccurrencesOfString:@" " withString:@""]; CGFloat price = self.priceField.text.floatValue; // 拼接插入数据的sql语句 NSString *sql = [NSString stringWithFormat:@"INSERT INTO t_SQLite(name,price) VALUES('%@',%f)", name, price]; char *errorMessage = NULL; sqlite3_exec(_sqlite, sql.UTF8String, NULL, NULL, &errorMessage); if (errorMessage) NSLog(@"----- 插入数据失败 -> errorMessage: %s -----", errorMessage); else NSLog(@"----- 插入数据成功 -----"); }
(2)删
* 注:这里我在 Main.storyboard 里 新增按钮下方拖放了一个输入框(UITextField)和一个删除按钮(UIButton),并建立关联
这里是以 id 为关键字进行定位到数据的,所以,这个 id 的值必须是已有的数据的 id 值
@interface ViewController () { sqlite3 *_sqlite; } @property (weak, nonatomic) IBOutlet UITextField *nameField; @property (weak, nonatomic) IBOutlet UITextField *priceField; @property (weak, nonatomic) IBOutlet UITextField *lbl; @end #pragma mark - 删 - (IBAction)deleteDataEvent:(UIButton *)sender { NSString *lbl = [self.lbl.text stringByReplacingOccurrencesOfString:@" " withString:@""]; // 拼接sql删除语句 NSString *sql = [NSString stringWithFormat:@"DELETE FROM t_SQLite where id=%ld", lbl.integerValue]; char *error = NULL; sqlite3_exec(_sqlite, sql.UTF8String, NULL, NULL, &error); if (error) NSLog(@"----- 删除数据失败 -> error: %s -----", error); else NSLog(@"----- 删除数据成功 -----"); }
(3)改
* 注:这里我在 Main.storyboard 里新拖了一个修改按钮(UIButton),并建立关联
这里是以 id 为关键字进行定位到数据的,所以,这个 id 的值必须是已有的数据的 id 值
#pragma mark - 改 - (IBAction)updateDataEvent:(UIButton *)sender { NSString *name = [self.nameField.text stringByReplacingOccurrencesOfString:@" " withString:@""]; NSString *price = [self.priceField.text stringByReplacingOccurrencesOfString:@" " withString:@""]; NSString *lbl = [self.lbl.text stringByReplacingOccurrencesOfString:@" " withString:@""]; // 拼接更新数据的sql语句 NSString *sql = [NSString stringWithFormat:@"update t_SQLite set name='%@',price='%@' where id=%@", name, price, lbl]; char *error = NULL; sqlite3_exec(_sqlite, sql.UTF8String, NULL, NULL, &error); if (error) NSLog(@"----- 更新数据失败 -> error: %s -----", error); else NSLog(@"----- 更新数据成功 -----"); }
大家可以观察上面的三个方法,会发现除了sql语句的拼接不一样以外,其他的地方几乎一模一样,所以,增删改的操作相对来说还是比较简单的。
(4)查
* sqlite3_prepare_v2函数是准备要执行sql查询的一个函数,可以当做这个函数就是用来做sql查询之前的准备工作的,它也是返回一个枚举作为准备工作的结果,SQLITE_OK则代表准备工作ok
* sqlite3_prepare_v2需要传入5个参数,第一个参数是数据库引用即(sqlite3* _shop),第二个参数是要执行的sql语句,第三个参数是sql语句的长度,第四个参数是查询结果stmt的引用,查询完成后,查询结果将会存入该引用,第五个参数是指向无法使用的部分的指针,一般不会用到,给NULL就可以了
* sqlite3_step(stmt)函数将会执行查询并且将查询到的当前记录存入到stmt(sqlite3_stmt * 类型)中
* 第一次执行sqlite3_step(stmt)将会将表中的第一条数据存入到stmt中,第二次执行sqlite3_step(stmt)将会把表中的第二条记录存入到stmt中
* 也就是说,while(sqlite3_step(stmt)==SQLITE_ROW)将会一条一条的去读取表中的记录,而SQLITE_ROW枚举判断的是有读取到数据行的情况
#pragma mark - 查 - (void)inquiryData { // 查询sql语句 const char *sql = "select * from t_SQLite"; // stmt用来取出查询结果 sqlite3_stmt *stmt = NULL; NSInteger state = sqlite3_prepare_v2(_sqlite, sql, -1, &stmt, NULL); // 准备成功,SQL语句正确 if (state == SQLITE_OK) // 成功指向一条记录 while (sqlite3_step(stmt) == SQLITE_ROW) { // 封装的实体 Shop *shop = [[Shop alloc] init]; //sqlite3_column_xxxx函数:它用来读取数据行中不同类型的数据,该函数的返回值就是读取到得数据内容,该函数需要2个参数, 第一个参数是存放数据的stmt,第二个参数是数据列下标 // 读取stmt中存储的第0列数据 shop.pid= sqlite3_column_int(stmt, 0); // 读取stmt中存储的第1列数据 const char *name = (const char*)sqlite3_column_text(stmt, 1); // 读取stmt中存储的第2列数据 const char *price = (const char*)sqlite3_column_text(stmt, 2); // 将C类型的字符串转换为oc类型的字符串并存储 shop.name = [NSString stringWithUTF8String:name]; // 将C类型的字符串转换为oc类型的字符串并存储 shop.price = [NSString stringWithUTF8String:price]; } else NSLog(@"----- 读取数据失败 -----");
对sqlite3的基本使用大致就这些,平时我们要用的也只是这些操作,其他的SQL操作正常情况下是不会涉及到。
接下来就是将上面的代码重复的运用到你的项目中!
这里介绍一些常用的SQL语句
- 增
// 插入单行 // INSERT INTO <表名> (列名1, 列名2, ...) VALUES (列值1, 列值2, ...) // 注:括号内的列值要与列名相对应! INSERT INTO student (, '牛八', '女')
- 删
// 删除 满足条件的行 // DELETE FROM <表名> WHERE <删除条件> DELETE FROM student WHERE name =
// 删除整个表 // TRUNCATE TABLE <表名> // 注意:删除表的所有行,但表的结构、列、约束、索引等不会被删除;不能用语有外建约束引用的表 TRUNCATE TABLE student
- 改
// 修改满足条件的数据内容 // UPDATE <表名> SET <列名=更新值> WHERE <更新条件> UPDATE student SET sex =
// 修改已有的表的列名 // ALTER TABLE `表名` CHANGE COLUMN `原列名` `新列名` 限制值得长度 ALTER TABLE `student` CHANGE COLUMN `Class` `department` varchar()
- 查
// 查询所有数据行和列 // SELECT * FROM 表名 // 说明:查询student表中所有行和列 SELECT * FROM student
// 精确条件查询 // SELECT * FROM 表名 WHERE 查询条件 SELECT * FROM student WHERE sex = '女'
// 使用like进行模糊查询 // 注意:like运算只用于字符串,所以仅与char和varchar数据类型联合使用 // 说明:查询显示表student中,name字段第一个字为牛的记录 SELECT * FROM student WHERE name LIKE '牛%' // 说明:查询显示表student中,name字段最后一个字为八的记录 SELECT * FROM student WHERE name LIKE '%八'
// 使用between在某个范围内进行查询 // SELECT * FROM 表名 WHERE 列名 BETWEEN 列值1 AND 列值2 // 说明:查询显示表student中id在909到911之间的记录 SELECT * FROM student WHERE AND
// 使用in在列举值内进行查询 // 说明:查询表student中id值为907或者909或者911的记录,显示name字段 SELECT name FROM student WHERE , , )
Objective-C访问SQLite的更多相关文章
- Qt5 开发 iOS 应用之访问 SQLite 数据库
开发环境: macOS 10.12.1 Xcode 8.1 Qt 5.8 iPhone 6S+iOS 10.1.1 源代码: 我在 Qt 程序里指定了数据库的名称来创建数据库,在 Win10.An ...
- 应用EF访问SQLite数据
创建项目,应用EF访问SQLite 1.创建项目 项目结构初始结构如下图所示,Netage.Data.SQLite 类库项目用于定义访问数据的接口和方法,Netage.SQLiteTest.UI 控制 ...
- 【Android】13.4 使用SQLite.NET.Async-PCL访问SQLite数据库
分类:C#.Android.VS2015: 创建日期:2016-02-27 一.简介 这一节演示如何利用以异步方式(async.await)访问SQLite数据库. 二.示例4运行截图 下面左图为初始 ...
- 【Android】13.2 使用自定义的CursorAdapter访问SQLite数据库
分类:C#.Android.VS2015: 创建日期:2016-02-26 一.简介 SQliteDemo1的例子演示了SimpleCursorAdapter的用法,本节我们将使用用途更广的自定义的游 ...
- 【Android】13.1 用Android自带的API访问SQLite数据库
分类:C#.Android.VS2015: 创建日期:2016-02-26 一.简介 这一节我们先来看看如何直接用Android自带的API创建和访问SQLite数据库. 1.创建SQLite数据库 ...
- 【Android】13.0 第13章 创建和访问SQLite数据库—本章示例主界面
分类:C#.Android.VS2015: 创建日期:2016-02-26 一.简介 Android 内置了三种数据存取方式:SQLite数据库.文件.SharedPreferences. 这一章我们 ...
- 并发访问sqlite数据库出现databse is locked的错误的一个解决办法
作者:朱金灿 来源:http://blog.csdn.net/clever101 在并发访问sqlite数据库会出现这样一个错误:databseis locked,这是sqlite数据库对并发支持不太 ...
- 【C#】使用EF访问Sqlite数据库
原文:[C#]使用EF访问Sqlite数据库 1. 先上Nuget下载对应的包 如图,搜索System.Data.SQLite下载安装即可,下载完之后带上依赖一共有这么几个: EntityFramew ...
- 以EntifyFramework DBFirst方式访问SQLite数据库
前面一直在找EF Code First方式来访问SQLite数据库,后面得出的结论是SQLite不支持 Code First, 虽然有非官方的库SQLite.CodeFirst可以使用,但一直没搞成功 ...
- Qt 程序访问 sqlite 权限错误
在Linux桌面上开发应用,想要拥有root权限,可是又需要弹窗申请.所以尽量避免这种情况发生. 另外:gksu,pkexec可以提供gui的root权限索取功能. 因为db文件是安装的时候放到etc ...
随机推荐
- 关于在android手机中腾讯、阿里产品不自定义虚拟键盘的想法
1,自定义虚拟键盘,影响用户体验.你每个用户的喜好不一样,都有自己心仪的一款输入法.腾讯或是阿里设计出来的输入法很难满足上亿用户的喜好,到时候又是一场口水战,再说了就是专业的输入法肯定要比应用里嵌套的 ...
- [MODX] 0. Mangement System Overview
In Modex, there are three tabs: Resoources, Elements & Files First: 'Files' is the place where t ...
- Servlet---JavaWeb技术的核心基础,JavaWeb框架的基石(二)
一.Servlet之Request Web服务器会对收到的每一次客户端http请求分别创建一个用于代表请求的request对象和代表响应的response对象.要获取客户端提交的数据需 ...
- 详解SQL Server连接(内连接、外连接、交叉连接)
在查询多个表时,我们经常会用“连接查询”.连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志. 什么是连接查询呢? 概念:根据两个表或多个表的列之间的关系,从这些表中查询数据 ...
- oracle 直接客户端使用
到oracle网站下载直接客户端,http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/winsoft.htm ...
- apache配置文件
httpd-vhost.conf文件中: <VirtualHost *:80> ServerAdmin webmaster@dummy-host2.example.com Do ...
- Qt... configure: error: Qt (>= Qt 2.2.2) (headers…
转载:http://blog.chinaunix.net/uid-23733724-id-290980.html 昨天开始在自己的fedora12下装qt~ 但是按照教程在/opt/Embed ...
- [Java]java反射随笔
类是面向对象的灵魂,一切事物都可以以类来抽象. 在java使用过程中,我们可能会经常用到一个反射的知识,只是别人都封装好的,如jdbc的加载驱动类有一句Class.for(“…jdbc…”).newI ...
- Python 基础【第四篇】参数
程序运行避免不了需要一些参数来支持 那么如何让程序接收参数呢?这里先简单的用sys模块的参数 sys.argv[]方法来实现参数获取 1.用法: import sys //导入sys模块后期会详细 ...
- [改善Java代码]自由选择字符串拼接方法
对一个字符串拼接有三种方法:加号,contact方法,StringBuffer或者StringBuilder的append方法,其中加号是最常用的.其他两种方式偶尔会出现在一些开源项目中,那么这三者有 ...