Cocos数据篇[3.4](6) ——SQLite3数据库基础用法

【唠叨】

在Cocos2d-x中,简单数据存储,可以使用UserDefault。那么如何存储大量,不规则的数据?我们可以使用 SQLite数据库 存储数据。SQLite 是使用非常广泛的 嵌入式数据库 ,它有小巧 、高效、跨平台、开源免费和易操作的特点。所以大量的被用于手机、PDA、MP3播放器、以及机顶盒设备。

SQLite数据库是使用C语言来编写的,因此在Cocos2d-x使用SQLite也是得心应手。

本文介绍一下SQLite3数据库的基础用法:增删改查。

PS:另外对于SQLite的可视化管理工具,本人使用的是 SQLiteStudio,这个就自行了解吧。

【参考】

http://cn.cocos2d-x.org/tutorial/show?id=1351   (【官方文档】SQLite集成与用法)

http://blog.chinaunix.net/uid-8447633-id-3321394.html   (SQLite3使用总结)



【SQLite3】

1、准备工作

Cocos引擎的external文件夹里的sqlite3好像只有两个 .h 文件,没有 sqlite3.c文件。所以我编译的时候一直编译不通过。后来去sqlite官网下了源文件,才编译成功的。

(1)首先,到下载sqlite3的源文件。

下载地址:http://www.sqlite.org/download.html

(2)将sqlite3的三个源文件拷贝到项目的Classes文件中,并导入到项目里。

如果是Android平台的话,还需要修改 Android.mk 文件。

2、SQLite3的基础API

这里只介绍一下SQLite3最基本的API,可以帮助你完成数据库的 增删改查 功能。

注意:SQLite3 数据库使用的编码格式为:UTF-8 。如果出现乱码的话,就将其转为 UTF-8 格式。

2.1、关键数据结构:sqlite3*

SQLite里最常用到的是:sqlite3* 类型。

从数据库打开开始,SQLite就要为这个类型准备好内存,直到数据库关闭,整个过程都需要用到这个类型。当数据库打开时开始,这个类型的变量就代表了你要操作的数据库。下面再详细介绍。

2.2、打开数据库:sqlite3_open

int sqlite3_open(const char *filename, sqlite3 **ppDb)

这个函数是用来打开数据库的。

(1)filename : 数据库文件名(如:"/Users/apple/Documents/data.db" )。文件名不需要一定存在,如果此文件不存在,sqlite 会自动建立它。如果它存在,就尝试把它当数据库文件来打开。

(2)ppDb : 即前面提到的关键数据结构。这个结构底层细节如何,你不要关它。

(3)返回值: 如果为 SQLITE_OK ,则成功打开数据库。

2.3、关闭数据库:sqlite3_close

int sqlite3_close(sqlite3 *)

这个函数是用来关闭数据库的。若不再使用数据库时,必须将数据库关闭,释放内存资源。

(1)sqlite3* : 即前面提到的关键数据结构。

(2)返回值: 如果为 SQLITE_OK ,则成功关闭数据库。

2.4、执行sql语句:sqlite3_exec

int sqlite3_exec(sqlite3*, const char *sql, int (*callback)(void*,int,char**,char**), void*, char **errmsg)

这个函数是用来执行sql语句的,对数据库进行:增删改查。

(1)sqlite3* : 即前面提到的关键数据结构。

(2)sql : 即sql语句(增删改查)。

(3)(*callback) : 执行exec时,每查到一条记录,就会调用这个回调函数(具体在 2.5 介绍)。

(4)void* : 传递数据,可以是任意值。会传递到回调函数callback,作为它的第一个参数传入。

(5)errmsg : 错误信息。

注意:后面三个参数,若不需要,可以填 NULL 。

2.5、sqlite3_exec的回调函数callback

int (*sqlite3_callback)(void* para, int col_num, char** col_value, char** col_name)

这个函数作为 sqlite3_exec 的第三个参数。执行exec时,每查询到一条记录,就会调用一次。

(1)para : 即 exec 的第四个参数,传递来的数据。

(2)col_num : 一条记录有多少个字段(即这条记录的列数)。

(3)col_value : 查询出来的数据(即:每个字段的值 )。它是个一维数组(不要以为是2维数组),每个元素都是一个字符串 char * 值,是一个字段内容。

(4)col_name : 每一个字段的字段名称(即:列名),与 col_value 对应。

2.6、不使用回调查询数据库:sqlite3_get_table

sqlite3_get_table(sqlite3 *db, const char *sql, char ***result, int *row, int *col, char **errmsg)

这个函数是用来查询数据库的。

(1)db : 即前面提到的关键数据结构。

(2)sql : 即sql查询语句。

(3)result : 查询结果。它依然一维数组(不要以为是二维数组,更不要以为是三维数组)。它内存布局是:第一行是字段名称,后面是紧接着是每个字段的值。即:0~col-1是字段名称,col~2*col-1是第一行记录,2*col~3*col-1是第二行记录,……以此类推。

(4)row : 行数。

(5)col  : 列数。

(6)errmsg : 错误信息。

注意:这个函数的 result 访问完后,需要使用 sqlite3_free_table(retult),释放资源。

3、使用方法

3.1、引入头文件

添加从SQLite官网下载的源代码 sqlite3.h 头文件。

//
	#include "sqlite3.h"
//

3.2、创建数据库

创建数据库,若文件不存在,SQLite会自动建立。若文件存在,就尝试把它当数据库文件来打开。

//
	// 数据库路径
	std::string path = "/soft/cocos2d-x-3.4/projects/Demo34/Resources/data.db";
	std::string sql; // sql语句
	int ret;         // 执行结果,SQLITE_OK表示成功执行

	// 创建sqlite数据库:sqlite3*
	sqlite3* pdb = nullptr;

	// 打开sqlite数据库:sqlite3_open
	ret = sqlite3_open(path.c_str(), &pdb);

	// 当sqllite数据库打开失败时
	if (ret != SQLITE_OK) {
		// 获得sqltite数据库打开错误的信息
		const char* errmsg = sqlite3_errmsg(pdb);
		CCLOG("sqlite open error: %s", errmsg);
		sqlite3_close(pdb);
		return false;
	}
//

3.3、创建表

创建一张表:create table 表名(ID , name , sex)

表名:student 。 有三个字段:ID、name、sex  (其中ID为主键自增)。

PS:创建表,不需要回调函数。sqlite3_exec 的后面三个参数都填 NULL 。

//
	// 创建表的sql语句:create table
	sql = "create table student(ID integer primary key autoincrement, name text, sex text)";

	// 执行sql语句:sqlite3_exec
	ret = sqlite3_exec(pdb, sql.c_str(), nullptr, nullptr, nullptr);

	if(ret != SQLITE_OK) {
		CCLOG("create table failed");
	}
//

3.4、插入数据(增)

插入三条数据:insert into 表名 value(1 , "name" , "sex")

PS:插入数据,不需要回调函数。sqlite3_exec 的后面三个参数都填 NULL 。

//
	// (1 , ‘student1‘ , ‘male‘)
	sql = "insert into student values(1, ‘student1‘, ‘male‘)";
	ret = sqlite3_exec(pdb, sql.c_str(), nullptr, nullptr, nullptr);
	if(ret != SQLITE_OK) {
		CCLOG("insert data failed!");
	}

	// (2 , ‘student3‘ , ‘female‘)
	sql = "insert into student values(2, ‘student2‘, ‘female‘)";
	ret = sqlite3_exec(pdb, sql.c_str(), nullptr, nullptr, nullptr);
	if(ret != SQLITE_OK) {
		CCLOG("insert data failed!");
	}

	// (3 , ‘student3‘ , ‘male‘)
	sql = "insert into student values(3, ‘student3‘, ‘male‘)";
	ret = sqlite3_exec(pdb, sql.c_str(), nullptr, nullptr, nullptr);
	if(ret != SQLITE_OK) {
		CCLOG("insert data failed!");
	}
//

3.5、查询数据,使用sqlite3_exec(查)

使用 sqlite3_exec 来查询:select * from 表名

//
	// 查询语句
	sql = "select * from student";
	ret = sqlite3_exec(pdb, sql.c_str(), &callback, (void*)"para", nullptr);

	// 回调函数
	int callback(void* para, int col_num, char** col_value, char** col_name)
	{
		CCLOG("%s : 总共有 %d 个字段", (char *)para , col_num);

		for (int i = 0; i < col_num; i++) {
			CCLOG("%s = %s", col_name[i], col_value[i]);
		}

		CCLOG("------------------------------"); // 分隔符

		return 0;
	}
//

控制台输出结果:

3.6、删除数据(删)

删除第一条记录:delete from 表名 where 条件

//
	// 删除第一条记录
	sql = "delete from student where ID = 1";
	ret = sqlite3_exec(pdb, sql.c_str(), nullptr, nullptr, nullptr);
	if(ret != SQLITE_OK) {
		CCLOG("delete data failed!");
	}
//

3.7、修改数据(改)

修改数据:update 表名 set name = "hello" where 条件

//
	// 修改第三条记录的 name 字段
	sql = "update student set name = ‘hello‘ where ID = 3";
	ret = sqlite3_exec(pdb, sql.c_str(), nullptr, nullptr, nullptr);
	if(ret != SQLITE_OK) {
		CCLOG("update data failed!");
	}
//

3.8、查询数据,使用sqlite3_get_table(查)

使用 sqlite3_get_table 来查询:select * from 表名

查询完后,不使用回调函数,而是直接保存查询结果。

//
	char** table; // 查询结果
	int r, c;     // 行数、列数

	sql = "select * from student";
	sqlite3_get_table(pdb, sql.c_str(), &table, &r, &c, nullptr);

	CCLOG("行数 is %d , 列数 is %d", r, c);

	// 第0行(0 ~ c-1),为字段名
	// 第1行(c ~ 2*c-1),第一条记录
	// ......
	for(int i = 0; i <= r; i++) {
		for(int j = 0; j < c; j++) {
			CCLOG("%s", table[i * c + j]);
		}
		CCLOG("------------------------------");
	}

	// 记得是否查询表
	sqlite3_free_table(table);
//

控制台输出结果:

可以看到 ID = 1 的数据已经被删除了,并且ID = 3 的数据name被改为了 " hello " 。

3.9、关闭数据库

最后,记得关闭数据库,否则会造成内存泄露。

//
	sqlite3_close(pdb);
//

【完整代码下载】:http://down.51cto.com/data/1983839

时间: 2024-10-14 05:34:47

Cocos数据篇[3.4](6) ——SQLite3数据库基础用法的相关文章

Cocos2d-x数据篇06:SQLite3数据库基础用法

尊重原创:http://cn.cocos2d-x.org/tutorial/show?id=2430 [前言] 在Cocos2d-x中,简单数据存储,可以使用UserDefault.那么如何存储大量,不规则的数据?我们可以使用 SQLite数据库 存储数据.SQLite 是使用非常广泛的 嵌入式数据库 ,它有小巧 .高效.跨平台.开源免费和易操作的特点.所以大量的被用于手机.PDA.MP3播放器.以及机顶盒设备. SQLite数据库是使用C语言来编写的,因此在Cocos2d-x使用SQLite也

Cocos数据篇[3.4](4) ——plist文件操作

[唠叨] 在Cocos中,plist文件 是非常常见的配置文件.它是特定格式的xml文件. 例如:小图打包成大图的纹理图片.制作粒子特效.帧动画等,都用到了plist文件作为配置文件. 本节要介绍的是:如何创建plist文件,以及读取plist文件中的数据信息. [扩展阅读] http://zh.wikipedia.org/wiki/Plist (维基百科) http://zengrong.net/post/1981.htm (COCOS2D-X中的PLIST文件格式详解) http://cn.

Cocos数据篇[3.4](2) ——Json数据操作

[唠叨] 在游戏中使用Json来储存数据,既方便读取,又方便管理. 比如CocosStudio 1.6之前版本导出的资源扩展名就是 .ExportJson 格式的. Cocos2d-x 3.x 加入了rapidjson库用于json解析.位于external/json下. 本节要介绍的就是:如何使用 rapidjson库 来操作处理json文件. [参考] http://www.w3school.com.cn/json/index.asp (W3School) http://cn.cocos2d

Cocos数据篇[3.4](5) ——CSV文件解析

[唠叨] 在一个游戏中,通常会有很多怪物.关卡.技能等数据,这些数据不可能在代码里写死,一般都会使用配置文件保存,使用时再加载到内存. CSV文件编辑起来十分简单,所以常常用来配置游戏的数据信息. 本文要介绍的是:如何读取CSV文件格式的数据. [扩展阅读] http://baike.baidu.com/subview/468993/5926031.htm (CSV百度百科) http://blog.csdn.net/stevenkylelee/article/details/38309147 

Cocos数据篇[3.4](3) ——XML数据操作

[唠叨] XML 即 可扩展标记语言,在游戏开发中,常用于保存游戏数据信息,如最高分.游戏等级等信息,和描述一些资源等. 加载动画的plist文件.瓦片地图编辑器到处的地图格式tmx文件,实际上都是特定格式的xml文件. 另外 UserDefault 单例类保存的数据,也是存储在xml文件中的. Cocos2d-x 已经加入了 tinyxml2库 用于xml的解析.3.x版本位于external/tinyxml2下. 本节要介绍的就是:如何使用 tinyxml2库 来操作处理xml文件. [参考

Cocos移植到Android的一些问题-SQLite3数据库移植问题

首选我们讨论一下SQLite3数据库移植问题.我们在第14章节介绍了在Win32平台使用SQLite3数据库,我们介绍了两种配置环境的方法:一种是使用Cocos2d-x提供的SQLite3库配置,另一种是从SQLite官网下载源代码拷贝的工程中.第一种方法配置起来比较麻烦,关键是Cocos2d-x提供的SQLite3库只是Win32没有其它平台的,目录结构如下所示.<游戏工程目录>\cocos2d\external\sqlite3│  Android.mk│├─include│      sq

Rails 使用sqlite3数据库 及数据操作基本命令

Rails默认使用sqlite3做为数据库,虽然很多人更喜欢mysql.但如果是学习用,sqlite3够了,因为它轻量,不需要安装. 首先对sqlite3做个简短的介绍:1.sqlite3不需要配置,不需要安装,也不需要管理员.最牛的是它没有服务器,仅是一个exe或dll2.数据库以文件形式保存在磁盘上,可以自由COPY使用3.因为sqlite3没有服务器监听端口,所以不能像mysql一样通过ip和端口远程连接数据库.如果想远程访问数据库,只能通过数据库文件共享方式 1.安装gem gem in

深入理解iPhone数据持久化(手把手教你iphone开发 – 基础篇)

在所有的移动开发平台数据持久化都是很重要的部分:在j2me中是rms或保存在应用程序的目录中,在symbian中可以保存在相应的磁盘目录中和数据库中.symbian中因为权限认证的原因,在3rd上大多数只能访问应用程序的private目录或其它系统共享目录.在iphone中,apple博采众长,提供了多种数据持久化的方法,下面笔者会逐个进行详细的讲解. iphone提供的数据持久化的方法,从数据保存的方式上讲可以分为三大部分:属性列表.对象归档.嵌入式数据库(SQLite3).其他方法. 一.属

iOS sqlite3数据库解析

看来从版本3.3.1基本上已经支持线程句柄的传递功能.具体限制我标记了一下.(6) Is SQLite threadsafe?SQLite is threadsafe. We make this concession since many users choose to ignore the advice given in the previous paragraph. But in order to be thread-safe, SQLite must be compiled with th