sqlite数据库的基本操作
2017-06-22 22:02
253 查看
今天来聊一聊sqlite数据库的一些基本操作, 之前一直用的是FMDB来操作数据库的, 但是也想对sqlite本身也做一个了解, 那我们就来一起学习一下.
sqlite数据库是一种轻量级数据库,被集成到用户程序中, 占用资源非常的低,在嵌入式设备中,占用内存很低而查询效率很高,因此广泛应用在各种移动客户端中;
简单,轻巧的足够小(C语言API ,4.43M)
快(比大部分的普通数据库都快)
支持的数据库大小至2TB,所以注定了它是一个跨平台利器,在Android与iOS下均能使用,而且完全可以写出通用的代码,方便我们移植。最后一个重要的原因就是原生的使用也是相当简单
Demo的操作环境: Xcode 8.3.3
忽略我的警告… :P
然后在你需要使用sqlite3的地方导入头文件
喏, 然后就可以愉快的开始使用了~
BTW: 我能说第一次我看到这个方法的时候以为是要手动写的, 自己定义了一套么.. :(
上面第一个参数就是数据库所存放的路径,如果有就直接用, 如果路径下没有数据库文件则系统会在此路径下创建一个数据库。至于第二个参数则是数据库的句柄引用,但此函数调用成功后此句柄将会保存打开数据库的句柄,此句柄在往后的数据库操作中需要用到。因此,可如下方式调用:
来解释一下句柄:
句柄在很多地方我们见到过,最常见的就是文件的句柄,我们要操纵一个文件,我们就要取得一个文件的句柄。句柄是个什么东西?其实很简单,句柄是一个东西的描述,他被定义为一个结构体,这个结构体可能会包含要描述的东西的具体信息,比如位置、大小、类型等等。我们有了这个描述信息我们就能去找到这个东西,然后操纵它。一句话:句柄是物体的描述结构体。
咱还可以理解为“把手” : 虽然你握住的只是把手,却能拉动整扇门,而且你根本不用在意那门长什么样子, 一扇门如果有多个把手,被不同的人(进程)握住,门往哪儿走就不好说了…
这是我定义的一个句柄:
关闭的时候把我们定义的句柄传入数据库即可对数据库进行关闭。调用方式如下:
面要注意的一点是,如果你有传入errorMsg参数,那么你必须在执行完sqlite3_exec后,执行sqlite3_free函数来释放errorMsg。否则就会造成内存泄露
然后你猜猜会报什么错? ;)
不明所以? 一脸蒙蔽? 恩…当时的我就是这个样子的! 为什么是null? 如果出了错都不知道原因是什么… :o
所以我用了第二种sqlite3_errmsg(_dbHandle)来打印错误信息,这是一个报错的函数,所以结果就很清楚了: 库程序调用顺序问题
上面的例子创建了一个数据后,那么我们可以往里面插入数据,我们可以使用insert语句将数据插入表中:代码如下所示:
打印输出:
4.3.2 删除数据
删除数据只是SQL语句的语法不同而已,其他都一样, 提供两种删除方式:
4.3.3 更改数据
同上, 其他都一样
我们查询数据库就使用sqlite3_prepare_v2和sqlite3_step两个函数搭配进行操作。其中sqlite3_prepare_v2是一个将SQL语句编译为sqlite内部一个结构体(sqlite3_stmt).该结构体中包含了将要执行的的SQL语句的信息。而sqlite3_step则是让转化后的SQL进行下一步的操作。因此通过这两个函数可以很方便的获取到数据库中的数据。本人建议使用此方式取得记录集。下面是这两个函数的声明:
第三个参数是用于指定SQL语句最大的长度,如果此参数为负数,则根据第二个参数中的第一个终结符为准作为一条完整的语句。如果为非负数,则以第二个参数的第一个终结符,或者指定的数字为准作为一条完整语句。第四个参数则是调用函数后返回的一个结构体,此结构体包含了相关语句的信息。关于第五个参数是用于指向前一条语句结束位置,一旦指定此参数,则参数指向位置的左边语句将不进行编译解析。
传入参数即为准备语句中的结构体对象。
例子:
这就是今天的关于sqlite数据库的内容, 感觉还差点什么, 明天想起来再加进去.
2017年06月22日22:01:38 Reborn_Tai
sqlite数据库是一种轻量级数据库,被集成到用户程序中, 占用资源非常的低,在嵌入式设备中,占用内存很低而查询效率很高,因此广泛应用在各种移动客户端中;
简单,轻巧的足够小(C语言API ,4.43M)
快(比大部分的普通数据库都快)
支持的数据库大小至2TB,所以注定了它是一个跨平台利器,在Android与iOS下均能使用,而且完全可以写出通用的代码,方便我们移植。最后一个重要的原因就是原生的使用也是相当简单
Demo的操作环境: Xcode 8.3.3
1. 导入
一图流:忽略我的警告… :P
然后在你需要使用sqlite3的地方导入头文件
#import <sqlite3.h>
喏, 然后就可以愉快的开始使用了~
2. 我想打开一个数据库!
下面就是sqlite3定义的打开数据库的方法:int sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ );
BTW: 我能说第一次我看到这个方法的时候以为是要手动写的, 自己定义了一套么.. :(
上面第一个参数就是数据库所存放的路径,如果有就直接用, 如果路径下没有数据库文件则系统会在此路径下创建一个数据库。至于第二个参数则是数据库的句柄引用,但此函数调用成功后此句柄将会保存打开数据库的句柄,此句柄在往后的数据库操作中需要用到。因此,可如下方式调用:
NSString *path = [NSString stringWithFormat:@"%@/Documents/demo.db",NSHomeDirectory()]; if (sqlite3_open([path UTF8String], &_dbHandle)==SQLITE_OK) { NSLog(@"打开数据库成功!"); }
来解释一下句柄:
句柄在很多地方我们见到过,最常见的就是文件的句柄,我们要操纵一个文件,我们就要取得一个文件的句柄。句柄是个什么东西?其实很简单,句柄是一个东西的描述,他被定义为一个结构体,这个结构体可能会包含要描述的东西的具体信息,比如位置、大小、类型等等。我们有了这个描述信息我们就能去找到这个东西,然后操纵它。一句话:句柄是物体的描述结构体。
咱还可以理解为“把手” : 虽然你握住的只是把手,却能拉动整扇门,而且你根本不用在意那门长什么样子, 一扇门如果有多个把手,被不同的人(进程)握住,门往哪儿走就不好说了…
这是我定义的一个句柄:
static sqlite3 *dbHandle;
3. 关闭数据库!
既然有打开数据库,那么就肯定有关闭数据库的操作了,我们要养成良好的习惯,当需要使用数据库的时候就执行sqlite3_open来打开数据库,等使用完数据库后就调用sqlite3_close函数来对数据库进行关闭。关于sqlite3_close函数声明如下:int sqlite3_close(sqlite3 *);
关闭的时候把我们定义的句柄传入数据库即可对数据库进行关闭。调用方式如下:
if (sqlite3_close(_dbHandle)==SQLITE_OK) { NSLog(@"关闭数据库成功!"); }else{ NSLog(@"error %s",sqlite3_errmsg(_dbHandle)); }
4. 数据库的两种基本操作
4.1 sqlite3_exec函数
常用的有两种方式可以操作数据库中的数据和调整结构, 第一种就是sqlite3_exec函数,这种方法一般用在增、删、改。这个函数不适合来查询数据库, 后面我们再介绍查询数据库的方法. 先来看看此方法的声明:int sqlite3_exec( sqlite3*, /* An open database 这是我们打开数据库的句柄*/ const char *sql, /* SQL to be evaluated 待执行的SQL语句*/ int (*callback)(void*,int,char**,char**), /* Callback function 回调函数,有固定的格式,你可以自己实现*/ void *, /* 1st argument to callback 回调函数的第一个参数*/ char **errmsg /* Error msg written here 如果方法执行后存在异常,那么这个参数保存的就是错误的描述信息*/ );
4.2 创建数据表
要想让数据库能够存储数据,那就必须得创建一个数据表才能进行数据操作。而数据表是可以包含不同的数据字段,这些字段可以指定不同的数据类型,存储不同的数据。我们建表时可以根据需要进行创建。下面的代码创建了一个叫做persons的数据表,其中包含了3个字段id、name和age. (如果对SQL语句不太熟悉的朋友可以参考相关方面资料), 写个实例来演示上面的sqlite3_exec函数:-(void)createTable { //因为sqlite3是C写的,所以传入的时候,sqlite语句要用C的形式传入,如果用NSString *createString = ***; 这种形式会报错 const char *createString = "create table if not exists persons (id integer primary key autoincrement, name varchar(256), age integer)"; char *errorMsg; BOOL result = sqlite3_exec(_dbHandle, createString, nil, nil, &errorMsg); if (result == SQLITE_OK) { NSLog(@"建表成功!"); }else{ NSLog(@"建表失败!Error:%s",sqlite3_errmsg(_dbHandle))); } sqlite3_free(errorMsg); }
面要注意的一点是,如果你有传入errorMsg参数,那么你必须在执行完sqlite3_exec后,执行sqlite3_free函数来释放errorMsg。否则就会造成内存泄露
有个需要注意的点:
先看两张图:然后你猜猜会报什么错? ;)
2017-06-22 17:44:53.764 SQLiteDemo[68053:2703014] 打开数据库成功! 2017-06-22 17:44:53.764 SQLiteDemo[68053:2703014] 关闭数据库成功! 2017-06-22 17:44:53.764 SQLiteDemo[68053:2703014] 建表失败!Error:(null) 2017-06-22 17:44:53.764 SQLiteDemo[68053:2703014] 插入数据失败! Error:library routine called out of sequence
不明所以? 一脸蒙蔽? 恩…当时的我就是这个样子的! 为什么是null? 如果出了错都不知道原因是什么… :o
所以我用了第二种sqlite3_errmsg(_dbHandle)来打印错误信息,这是一个报错的函数,所以结果就很清楚了: 库程序调用顺序问题
4.3 增 ! 删 ! 改 !
4.3.1 插入数据上面的例子创建了一个数据后,那么我们可以往里面插入数据,我们可以使用insert语句将数据插入表中:代码如下所示:
-(void)insertInfo { const char *insert = "insert into persons (name,age) values ('阿童木',5)"; char *errorMsg; BOOL result = sqlite3_exec(_dbHandle, insert, nil, nil, &errorMsg); if (result == SQLITE_OK) { NSLog(@"插入数据成功!"); }else{ NSLog(@"插入数据失败! Error:%s",sqlite3_errmsg(_dbHandle)); } }
打印输出:
2017-06-22 17:39:56.379 SQLiteDemo[67920:2698580] 插入数据成功!
4.3.2 删除数据
删除数据只是SQL语句的语法不同而已,其他都一样, 提供两种删除方式:
delete from persons; //会直接删除所有的数据,但是不会清空自动增长列的标识。 delete from persons where id = 8; //根据id删除
-(void)deleteInfo { const char *delete = "delete from persons where id = 1"; BOOL result = sqlite3_exec(_dbHandle, delete, nil, nil, &errorMsg); if (result == SQLITE_OK) { NSLog(@"删除数据成功!"); }else{ NSLog(@"删除数据失败!Error:%s",sqlite3_errmsg(_dbHandle)); } }
4.3.3 更改数据
同上, 其他都一样
const char *change = "update persons set name = '铁甲小宝' age = '40' where id = 2";
4.4 重点: 查 !
sqlite3_prepare_v2和sqlite3_step函数我们查询数据库就使用sqlite3_prepare_v2和sqlite3_step两个函数搭配进行操作。其中sqlite3_prepare_v2是一个将SQL语句编译为sqlite内部一个结构体(sqlite3_stmt).该结构体中包含了将要执行的的SQL语句的信息。而sqlite3_step则是让转化后的SQL进行下一步的操作。因此通过这两个函数可以很方便的获取到数据库中的数据。本人建议使用此方式取得记录集。下面是这两个函数的声明:
int sqlite3_prepare_v2( sqlite3 *db, /* Database handle 句柄*/ const char *zSql, /* SQL statement, UTF-8 encoded SQL语句 */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ );
第三个参数是用于指定SQL语句最大的长度,如果此参数为负数,则根据第二个参数中的第一个终结符为准作为一条完整的语句。如果为非负数,则以第二个参数的第一个终结符,或者指定的数字为准作为一条完整语句。第四个参数则是调用函数后返回的一个结构体,此结构体包含了相关语句的信息。关于第五个参数是用于指向前一条语句结束位置,一旦指定此参数,则参数指向位置的左边语句将不进行编译解析。
sqlite3_step(sqlite3_stmt *);
传入参数即为准备语句中的结构体对象。
例子:
-(void)searchInfo { //创建数组 存数据 NSMutableArray *array = [[NSMutableArray alloc]init]; const char *select = "select * from persons where name = '阿童木'"; //sqlite3_prepare_v2的参数第一个是数据库连接,第二个是sql语句,第三个是这个语句的长度传入-1表示到第一个null终止符为止,第四个是返回一个语句对象,第五个是返回一个指向该sql语句的第一个字节的指针 int result = sqlite3_prepare_v2(_dbHandle, select, -1, &stmt, nil); if (result == SQLITE_OK) { // 开始遍历 每调一次sqlite3_step函数,stmt就会指向下一条记录 while (sqlite3_step(stmt) == SQLITE_ROW) { int ID = sqlite3_column_int(stmt, 0); // 取出第0列字段的值(int类型的值) const unsigned char *name = sqlite3_column_text(stmt, 1); // 取出第1列字段的值(text类型的值) int age = sqlite3_column_int(stmt, 2); // 取出第2列字段的值(int类型的值) //将C字符串转换为OC字符串 NSString *name1 = [[NSString alloc]initWithUTF8String:(const char *)name]; //将model实例化 并把取出来的数据存入model ZTPerson *p = [[ZTPerson alloc]init]; p.name = name1; p.age = age; p.ID = ID; [array addObject:p]; } }else{ NSLog(@"查询语句有问题,查询失败!"); } NSLog(@"%@",array); }
这就是今天的关于sqlite数据库的内容, 感觉还差点什么, 明天想起来再加进去.
2017年06月22日22:01:38 Reborn_Tai
相关文章推荐
- 数据库 SQLite数据库基本操作
- Android 存储学习之SQLite数据库的基本操作 (使用API操作数据库)
- sqlite数据库基本操作
- IOS--Sqlite数据库增删改查基本操作
- SQLite数据库的基本操作指令集合
- Android应用中内嵌SQLite数据库的基本操作指南
- Android操作SQLite数据库基本模式
- 【Android基础篇】SQLite数据库的增删改查基本操作
- sqlite数据库的基本增删改查操作MainActivity类代码
- SQLite数据库储存图片信息,GridView显示,基本实现添加、删除图标操作 ... ...
- SQLite数据库安装及基本操作指南
- ios Sqlite数据库增删改查基本操作
- Android 存储学习之SQLite数据库的基本操作
- android中SQLite数据库的基本操作以及重要方法介绍
- 数据库 SQLite数据库基本操作
- iOS Sqlite数据库增删改查基本操作
- sqlite数据库的基本操作基于FMDatabase(创建数据库,创建表,对标进行增,删,改,查)
- 安卓中的SQLite数据库的基本操作1
- Android中Sqlite数据库简介及基本操作