热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SQLite使用总结

SQLite数据库操作是移动开发中非常基础也非常重要的一部分,本文将从SQLite的概念到SQLite在iOS中的使用来介绍它。SQLite简介SQLite(英语发音:赊扣耐特)是

SQLite数据库操作是移动开发中非常基础也非常重要的一部分,本文将从SQLite的概念到SQLite在iOS中的使用来介绍它。

SQLite简介

SQLite (英语发音:赊扣耐特)是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C程序库中。与许多其它数据库管理系统不同,SQLite不是一个客户端/服务器结构的数据库引擎,而是被集成在用户程序中。
SQLite遵守ACID,实现了大多数SQL标准。它使用动态的、弱类型的SQL语法。它作为嵌入式数据库,是应用程序,如网页浏览器,在本地/客户端存储数据的常见选择。它可能是最广泛部署的数据库引擎,因为它正在被一些流行的浏览器、操作系统、嵌入式系统所使用。同时,它有许多程序设计语言的语言绑定。
维基百科

关于数据库一般划分为五大类型:

  • 关系型
  • 键-值型
  • 多列型
  • 面向文档型
  • 图型

目前应用最广的应该是关系型数据库(Relational DataBase Management System,RDBMS),它是以集合理论为基础的系统,实现为具有行和列的二维表。与RDBMS交互的标准方法是结构化查询语言(Structured Query Language,SQL)。

今天的主角SQLite就属于关系型数据库。SQLite是一个轻量级的库(只包含一个.h文件和一个.c文件,大概有八万多行代码),支持很多种语言的编程接口,包括C/C++、Java、Python、dotNet、Ruby、Perl等等。作为一款开源的嵌入式数据库,SQLite拥有强大而灵活的关系型数据库前端和简单而紧凑的B-tree后端。因此你无需任何配置,不用考虑平台限制和许可便将其放入到你的程序中。(目前sqlite版本为sqlite3)

SQLite是一款被广泛应用于移动设备的数据库,本文将主要介绍如何在iOS上使用SQLite。

以下是SQLite体系结构图

《SQLite使用总结》 sqlite体系结构图

SQLite的基础操作

首先要注意的是SQLite是忽略大小写的,为了不方便阅读,以下例子中我将关键字全部小写。

根据SQL惯例,称关系为表(TABLE),属性为列(COLUMN),元组为行(ROW)。最基本的数据库操作无非就是创建、读取、更新和删除。忽略创建就变成了我们常说的”增删改查”。下面是iOS中的基本操作例子。

创建数据库

这里使用到的方法为sqlite3_open,如果指定沙盒路径下不存在数据库,则先创建,再打开。

sqlite3 *_db;
NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)] objectAtIndex:0];
NSString *_dbPath = [documents stringByAppendingPathComponent:@"person.sqlite"];
int result = sqlite3_open(_dbPath.UTF8String,&_db);
if (result == SQLITE_OK) {
NSLog(@"open success");
} else {
NSLog(@"open failed");
}

创建数据表

NSString *sqlCreateTable = @"create table if not exists person (id integer primary key autoincrement,username text,age integer,gender integer,birthday numeric)";
char *error = NULL;
int result = sqlite3_exec(_db,sqlCreateTable.UTF8String,NULL,NULL ,&error);
if (error) {
NSLog(@"sqlite execute error");
sqlite3_free(error);
}

创建完毕可以在沙盒中查看数据库,表结构如下

《SQLite使用总结》 person.sqlite

插入数据

NSString *sqlInsert = [NSString stringWithFromat:@"insert into person(username,age,gender,birthday) values(?,?,?,?)",@"小明",@(22),@(1),[NSDate date]] ;
char *errorMsg = NULL;
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(_db, sqlInsert.UTF8String, -1, &stmt, NULL) == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, [username UTF8String], -1, NULL);
sqlite3_bind_int(stmt, 2, [age intValue]);
sqlite3_bind_int(stmt, 3, [gender intValue]);
sqlite3_bind_double(stmt, 4, [birthday timeIntervalSince1970]);
}
if (sqlite3_step(stmt) != SQLITE_DONE)
NSLog(@"insert error");

插入之后

《SQLite使用总结》 sqliteInsert

删除数据

删除指定姓名的数据

NSString *sqlDelete = [NSString stringWithFromat:@"delete from person where username=?",username] ;
sqlite3_stmt *stmt = NULL;
int result = sqlite3_prepare_v2(_db, sqlDelete.UTF8String, -1, &stmt, NULL);
if (result != SQLITE_OK) {
NSLog("sqlite stmt prepare error");
return NO;
}
sqlite3_bind_text(stmt, 1, username.UTF8String, -1, NULL);
result = sqlite3_step(stmt);
sqlite3_finalize(stmt);
if (result == SQLITE_ERROR) {
NSLog(@"delete error");
return NO;
}

查找数据

查找指定姓名的数据

NSString *sqlQuery = [NSString stringWithFromat:@"select * from person where username=%@",username] ;
sqlite3_stmt * statement;

if (sqlite3_prepare_v2(db, [sqlQuery UTF8String], -1, &statement, nil) == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, username.UTF8String, -1, NULL);
if (sqlite3_step(statement) == SQLITE_ROW) {
char *username = (char*)sqlite3_column_text(statement, 1);
NSString *usernameStr = [[NSString alloc]initWithUTF8String:username];
int age = sqlite3_column_int(statement, 2);
int gender = sqlite3_column_int(statement, 3);
double birthday = sqlite3_column_double(statement, 4);
NSDate *birthdayDate = [NSDate dateWithTimeIntervalSince1970:birthday];

}
}

另外在sql语句中还有一些运算符可以帮助快速过滤数据

  • like
    like是搜索中使用比较广的运算符。like比较列值和给定模式字符串,%匹配任意数量的任何字符,_匹配一个字符。(like只能用于简单的通配符,更强大的字符串匹配语法是正则表达式)
  • order by
    搜索结果按照关键字的升序(asc)或降序(desc)排列
  • limit
    限制返回的数据量 ,可以与offset配合使用
    SELECT username,age,gender FROM person LIMIT 3 OFFSET 2;
    从第3行开始(默认第一行,偏移两行),取3条数据
  • distinct
    消除所有重复的数据
  • group by
    根据指定规则对数据进行分组
    SELECT name,sum(age) from person GROUP BY name;
    根据名字获取personn表中的 name和age字段,同名的age累加
  • 聚合函数
    上例中的sum()便是聚合函数,它从一组记录中计算聚合值,类似的聚合函数还有avg(),count(),min(),max()等

修改数据

修改指定姓名的数据的年龄

NSString *sqlUpdate = [NSString stringWithFromat:@"update person set age=? where username=?",age,username] ;
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(_db, sqlUpdate.UTF8String, -1, &stmt, NULL) == SQLITE_OK) {
sqlite3_bind_int(stmt, 1, (int)age(NULL));
sqlite3_bind_text(stmt, 2, username.UTF8String, -1, NULL);
int result = sqlite3_step(stmt);
if (result != SQLITE_DONE) {
NSLog(@"update error");
return NO;
}
}

SQLite的高级使用

事务

事务保障了关系数据库的一致性,事务的准则是,要么全部成功,要么全部失败。
当发出begin命令时,事务将持续到调用commit或rollback,或者sql命令引起约束违反进而导致rollback。
一般情况下,锁持续时间隐藏在事务持续时间内,他们总是一起结束。下图可以看到事务的声明周期和锁状态

《SQLite使用总结》 sqlite锁状态

事务的控制主要有三条命令

  • BEGIN TRANSACTION :开始处理事务
  • COMMIT:把事务调用的更改保存到数据库中 或者用END TRANSACTION
  • ROLLBACK:回滚
    在iOS中的操作实际上就是执行一条sql语句,三条命令对应的sql语句如下:
    begin: @”begin exclusive transaction”
    commit: @”commit transaction”
    rollback: @”rollback transaction”

PS : 另外可以创建延迟事务,也可以根据保存点的名字回滚到指定版本

子查询

子查询是指select语句中嵌套select语句,通常应用在where子句,特别是in操作符中.例如
select count(*) from person where username in (select username from family where age=20 or age=22);

复合查询

复合查询是用来处理多个查询的结果,SQLite中对应使用关键字union,intersectexcept

UNION : 用于合并两个或多个select语句的结果,不返回任何重复的行,为了使用union,每个select被选择的列数必须相同
INTERSECT : 操作输入两个关系A和B,选择那些既在A也在B的行。
EXCEPT : 操作输入两个关系A和B,找出所有在A但不在B的行。

例如:

select username,age,gender from person
join family on person.username=family.username
union all
select username,age,gender from person
left outer join family on person.username=family.username;

join是把person和family的每一行进行比较,找到名字相同的行,并将列值合并成一个结果行,完整写法是inner join ,inner是可选的。

outer join指外连接,标准的SQL定义了三种外连接left,right和full,SQLite只支持left。左外连接主要看左边的表,先把左边表全部显示,右边满足条件 person.username=family.username的显示,不满足的显示为空。

小结

关于SQLite的使用还有很多,比如触发器、视图、注入等等。但是在实际使用中很少用到这些,所以考虑到篇幅的原因暂时先省了。另外在sqlite存取数据中还有一个比较特殊的blob类型,用来存取二进制文件,实际上只是多了一步字节长度的存取,以后有空会补上。

如果想了解SQLite的底层实现机制可参考下列文章:

  • 《SQLite源码分析》
  • 《SQLite中的B-tree、B+tree》
  • 《B-Tree和B+Tree》。

参考

  • http://www.runoob.com/sqlite/sqlite-view.html
  • http://my.oschina.net/u/587236/blog/129022
  • https://www.sqlite.org/foreignkeys.html

推荐阅读
  • 安装mysqlclient失败解决办法
    本文介绍了在MAC系统中,使用django使用mysql数据库报错的解决办法。通过源码安装mysqlclient或将mysql_config添加到系统环境变量中,可以解决安装mysqlclient失败的问题。同时,还介绍了查看mysql安装路径和使配置文件生效的方法。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 本文介绍了PhysioNet网站提供的生理信号处理工具箱WFDB Toolbox for Matlab的安装和使用方法。通过下载并添加到Matlab路径中或直接在Matlab中输入相关内容,即可完成安装。该工具箱提供了一系列函数,可以方便地处理生理信号数据。详细的安装和使用方法可以参考本文内容。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • Hibernate延迟加载深入分析-集合属性的延迟加载策略
    本文深入分析了Hibernate延迟加载的机制,特别是集合属性的延迟加载策略。通过延迟加载,可以降低系统的内存开销,提高Hibernate的运行性能。对于集合属性,推荐使用延迟加载策略,即在系统需要使用集合属性时才从数据库装载关联的数据,避免一次加载所有集合属性导致性能下降。 ... [详细]
  • 云原生应用最佳开发实践之十二原则(12factor)
    目录简介一、基准代码二、依赖三、配置四、后端配置五、构建、发布、运行六、进程七、端口绑定八、并发九、易处理十、开发与线上环境等价十一、日志十二、进程管理当 ... [详细]
  • {moduleinfo:{card_count:[{count_phone:1,count:1}],search_count:[{count_phone:4 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 实现一个通讯录系统,可添加、删除、修改、查找、显示、清空、排序通讯录信息
    本文介绍了如何实现一个通讯录系统,该系统可以实现添加、删除、修改、查找、显示、清空、排序通讯录信息的功能。通过定义结构体LINK和PEOPLE来存储通讯录信息,使用相关函数来实现各项功能。详细介绍了每个功能的实现方法。 ... [详细]
  • python3 nmap函数简介及使用方法
    本文介绍了python3 nmap函数的简介及使用方法,python-nmap是一个使用nmap进行端口扫描的python库,它可以生成nmap扫描报告,并帮助系统管理员进行自动化扫描任务和生成报告。同时,它也支持nmap脚本输出。文章详细介绍了python-nmap的几个py文件的功能和用途,包括__init__.py、nmap.py和test.py。__init__.py主要导入基本信息,nmap.py用于调用nmap的功能进行扫描,test.py用于测试是否可以利用nmap的扫描功能。 ... [详细]
  • 本文介绍了Foundation框架中一些常用的结构体和类,包括表示范围作用的NSRange结构体的创建方式,处理几何图形的数据类型NSPoint和NSSize,以及由点和大小复合而成的矩形数据类型NSRect。同时还介绍了创建这些数据类型的方法,以及字符串类NSString的使用方法。 ... [详细]
author-avatar
turneerpelliccia_291
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有