SQLite应用之实例代码
目录
一、获取表的Schema信息
二、常规数据插入
三、高效的批量数据插入
四、数据查询
一、获取表的Schema信息
1). 动态创建表。
2). 根据sqlite3提供的API,获取表字段的信息,如字段数量以及每个字段的类型。
3). 删除该表。
见以下代码及关键性注释:
#include <sqlite3.h>
#include <string>
using namespace std;
void doTest()
{
sqlite3* conn = NULL;
//1. 打开数据库
int result = sqlite3_open("D:/mytest.db",&conn);
if (result != SQLITE_OK) {
sqlite3_close(conn);
return;
}
const char* createTableSQL =
"CREATE TABLE TESTTABLE (int_col INT, float_col REAL, string_col TEXT)";
sqlite3_stmt* stmt = NULL;
int len = strlen(createTableSQL);
//2. 准备创建数据表,如果创建失败,需要用sqlite3_finalize释放sqlite3_stmt对象,以防止内存泄露。
if (sqlite3_prepare_v2(conn,createTableSQL,len,&stmt,NULL) != SQLITE_OK) {
if (stmt)
sqlite3_finalize(stmt);
sqlite3_close(conn);
return;
}
//3. 通过sqlite3_step命令执行创建表的语句。对于DDL和DML语句而言,sqlite3_step执行正确的返回值只有SQLITE_DONE。
//对于SELECT查询而言,如果有数据返回SQLITE_ROW,当到达结果集末尾时则返回SQLITE_DONE。
if (sqlite3_step(stmt) != SQLITE_DONE) {
sqlite3_finalize(stmt);
sqlite3_close(conn);
return;
}
//4. 释放创建表语句对象的资源。
sqlite3_finalize(stmt);
printf("Succeed to create test table now.\n");
//5. 构造查询表数据的sqlite3_stmt对象。
const char* selectSQL = "SELECT * FROM TESTTABLE WHERE 1 = 0";
sqlite3_stmt* stmt2 = NULL;
if (sqlite3_prepare_v2(conn,selectSQL,strlen(selectSQL),&stmt2,NULL) != SQLITE_OK) {
if (stmt2)
sqlite3_finalize(stmt2);
sqlite3_close(conn);
return;
}
//6. 根据select语句的对象,获取结果集中的字段数量。
int fieldCount = sqlite3_column_count(stmt2);
printf("The column count is %d.\n",fieldCount);
//7. 遍历结果集中每个字段meta信息,并获取其声明时的类型。
; i < fieldCount; ++i) {
//由于此时Table中并不存在数据,再有就是SQLite中的数据类型本身是动态的,所以在没有数据时无法通过sqlite3_column_type函数获取,此时sqlite3_column_type只会返回SQLITE_NULL,
//直到有数据时才能返回具体的类型,因此这里使用了sqlite3_column_decltype函数来获取表声明时给出的声明类型。
string stype = sqlite3_column_decltype(stmt2,i);
stype = strlwr((char*)stype.c_str());
//数据类型以决定字段亲缘性的规则解析
if (stype.find("int") != string::npos) {
printf("The type of %dth column is INTEGER.\n",i);
} else if (stype.find("char") != string::npos
|| stype.find("text") != string::npos) {
printf("The type of %dth column is TEXT.\n",i);
} else if (stype.find("real") != string::npos
|| stype.find("floa") != string::npos
|| stype.find("doub") != string::npos ) {
printf("The type of %dth column is DOUBLE.\n",i);
}
}
sqlite3_finalize(stmt2);
//8. 为了方便下一次测试运行,我们这里需要删除该函数创建的数据表,否则在下次运行时将无法创建该表,因为它已经存在。
const char* dropSQL = "DROP TABLE TESTTABLE";
sqlite3_stmt* stmt3 = NULL;
if (sqlite3_prepare_v2(conn,dropSQL,strlen(dropSQL),&stmt3,NULL) != SQLITE_OK) {
if (stmt3)
sqlite3_finalize(stmt3);
sqlite3_close(conn);
return;
}
if (sqlite3_step(stmt3) == SQLITE_DONE) {
printf("The test table has been dropped.\n");
}
sqlite3_finalize(stmt3);
sqlite3_close(conn);
}
int main()
{
doTest();
;
}
//输出结果为:
//Succeed to create test table now.
//The column count is 3.
//The type of 0th column is INTEGER.
//The type of 1th column is DOUBLE.
//The type of 2th column is TEXT.
//The test table has been dropped.
二、常规数据插入
1). 创建测试数据表。
2). 通过INSERT语句插入测试数据。
3). 删除测试表。
见以下代码及关键性注释:
#include <sqlite3.h>
#include <string>
#include <stdio.h>
using namespace std;
void doTest()
{
sqlite3* conn = NULL;
//1. 打开数据库
int result = sqlite3_open("D:/mytest.db",&conn);
if (result != SQLITE_OK) {
sqlite3_close(conn);
return;
}
const char* createTableSQL =
"CREATE TABLE TESTTABLE (int_col INT, float_col REAL, string_col TEXT)";
sqlite3_stmt* stmt = NULL;
int len = strlen(createTableSQL);
//2. 准备创建数据表,如果创建失败,需要用sqlite3_finalize释放sqlite3_stmt对象,以防止内存泄露。
if (sqlite3_prepare_v2(conn,createTableSQL,len,&stmt,NULL) != SQLITE_OK) {
if (stmt)
sqlite3_finalize(stmt);
sqlite3_close(conn);
return;
}
//3. 通过sqlite3_step命令执行创建表的语句。对于DDL和DML语句而言,sqlite3_step执行正确的返回值只有SQLITE_DONE。
//对于SELECT查询而言,如果有数据返回SQLITE_ROW,当到达结果集末尾时则返回SQLITE_DONE。
if (sqlite3_step(stmt) != SQLITE_DONE) {
sqlite3_finalize(stmt);
sqlite3_close(conn);
return;
}
//4. 释放创建表语句对象的资源。
sqlite3_finalize(stmt);
printf("Succeed to create test table now.\n");
;
//5. 构建插入数据的sqlite3_stmt对象。
const char* insertSQL = "INSERT INTO TESTTABLE VALUES(%d,%f,'%s')";
const char* testString = "this is a test.";
];
sqlite3_stmt* stmt2 = NULL;
; i < insertCount; ++i) {
sprintf(sql,insertSQL,i,i * 1.0,testString);
if (sqlite3_prepare_v2(conn,sql,strlen(sql),&stmt2,NULL) != SQLITE_OK) {
if (stmt2)
sqlite3_finalize(stmt2);
sqlite3_close(conn);
return;
}
if (sqlite3_step(stmt2) != SQLITE_DONE) {
sqlite3_finalize(stmt2);
sqlite3_close(conn);
return;
}
printf("Insert Succeed.\n");
}
sqlite3_finalize(stmt2);
//6. 为了方便下一次测试运行,我们这里需要删除该函数创建的数据表,否则在下次运行时将无法创建该表,因为它已经存在。
const char* dropSQL = "DROP TABLE TESTTABLE";
sqlite3_stmt* stmt3 = NULL;
if (sqlite3_prepare_v2(conn,dropSQL,strlen(dropSQL),&stmt3,NULL) != SQLITE_OK) {
if (stmt3)
sqlite3_finalize(stmt3);
sqlite3_close(conn);
return;
}
if (sqlite3_step(stmt3) == SQLITE_DONE) {
printf("The test table has been dropped.\n");
}
sqlite3_finalize(stmt3);
sqlite3_close(conn);
}
int main()
{
doTest();
;
}
//输出结果如下:
//Succeed to create test table now.
//Insert Succeed.
//Insert Succeed.
//Insert Succeed.
//Insert Succeed.
//Insert Succeed.
//Insert Succeed.
//Insert Succeed.
//Insert Succeed.
//Insert Succeed.
//Insert Succeed.
//The test table has been dropped.
三、高效的批量数据插入
在给出操作步骤之前先简单说明一下批量插入的概念,以帮助大家阅读其后的示例代码。事实上,批量插入并不是什么新的概念,在其它关系型数据库的C接口API中都提供了一定的支持,只是接口的实现方式不同而已。纵观众多流行的数据库接口,如OCI(Oracle API)、MySQL API和PostgreSQL API等,OCI提供的编程接口最为方便,实现方式也最为高效。SQLite作为一种简单灵活的嵌入式数据库也同样提供了该功能,但是实现方式并不像其他数据库那样方便明显,它只是通过一种隐含的技巧来达到批量插入的目的,其逻辑如下:
1). 开始一个事物,以保证后面的数据操作语句均在该事物内完成。在SQLite中,如果没有手工开启一个事物,其所有的DML语句都是在自动提交模式下工作的,既每次操作后数据均被自动提交并写入磁盘文件。然而在非自动提交模式下,只有当其所在的事物被手工COMMIT之后才会将修改的数据写入到磁盘中,之前修改的数据都是仅仅驻留在内存中。显而易见,这样的批量写入方式在效率上势必会远远优于多迭代式的单次写入操作。
2). 基于变量绑定的方式准备待插入的数据,这样可以节省大量的sqlite3_prepare_v2函数调用次数,从而节省了多次将同一SQL语句编译成SQLite内部识别的字节码所用的时间。事实上,SQLite的官方文档中已经明确指出,在很多时候sqlite3_prepare_v2函数的执行时间要多于sqlite3_step函数的执行时间,因此建议使用者要尽量避免重复调用sqlite3_prepare_v2函数。在我们的实现中,如果想避免此类开销,只需将待插入的数据以变量的形式绑定到SQL语句中,这样该SQL语句仅需调用sqlite3_prepare_v2函数编译一次即可,其后的操作只是替换不同的变量数值。
3). 在完成所有的数据插入后显式的提交事物。提交后,SQLite会将当前连接自动恢复为自动提交模式。
下面是示例代码的实现步骤:
1). 创建测试数据表。
2). 通过执行BEGIN TRANSACTION语句手工开启一个事物。
3). 准备插入语句及相关的绑定变量。
4). 迭代式插入数据。
5). 完成后通过执行COMMIT语句提交事物。
6). 删除测试表。
见以下代码及关键性注释:
#include <sqlite3.h>
#include <string>
#include <stdio.h>
using namespace std;
void doTest()
{
sqlite3* conn = NULL;
//1. 打开数据库
int result = sqlite3_open("D:/mytest.db",&conn);
if (result != SQLITE_OK) {
sqlite3_close(conn);
return;
}
const char* createTableSQL =
"CREATE TABLE TESTTABLE (int_col INT, float_col REAL, string_col TEXT)";
sqlite3_stmt* stmt = NULL;
int len = strlen(createTableSQL);
//2. 准备创建数据表,如果创建失败,需要用sqlite3_finalize释放sqlite3_stmt对象,以防止内存泄露。
if (sqlite3_prepare_v2(conn,createTableSQL,len,&stmt,NULL) != SQLITE_OK) {
if (stmt)
sqlite3_finalize(stmt);
sqlite3_close(conn);
return;
}
//3. 通过sqlite3_step命令执行创建表的语句。对于DDL和DML语句而言,sqlite3_step执行正确的返回值只有SQLITE_DONE。
//对于SELECT查询而言,如果有数据返回SQLITE_ROW,当到达结果集末尾时则返回SQLITE_DONE。
if (sqlite3_step(stmt) != SQLITE_DONE) {
sqlite3_finalize(stmt);
sqlite3_close(conn);
return;
}
//4. 释放创建表语句对象的资源。
sqlite3_finalize(stmt);
printf("Succeed to create test table now.\n");
//5. 显式的开启一个事物。
sqlite3_stmt* stmt2 = NULL;
const char* beginSQL = "BEGIN TRANSACTION";
if (sqlite3_prepare_v2(conn,beginSQL,strlen(beginSQL),&stmt2,NULL) != SQLITE_OK) {
if (stmt2)
sqlite3_finalize(stmt2);
sqlite3_close(conn);
return;
}
if (sqlite3_step(stmt2) != SQLITE_DONE) {
sqlite3_finalize(stmt2);
sqlite3_close(conn);
return;
}
sqlite3_finalize(stmt2);
//6. 构建基于绑定变量的插入数据。
const char* insertSQL = "INSERT INTO TESTTABLE VALUES(?,?,?)";
sqlite3_stmt* stmt3 = NULL;
if (sqlite3_prepare_v2(conn,insertSQL,strlen(insertSQL),&stmt3,NULL) != SQLITE_OK) {
if (stmt3)
sqlite3_finalize(stmt3);
sqlite3_close(conn);
return;
}
;
const char* strData = "This is a test.";
//7. 基于已有的SQL语句,迭代的绑定不同的变量数据
; i < insertCount; ++i) {
//在绑定时,最左面的变量索引值是1。
sqlite3_bind_int(stmt3,,i);
sqlite3_bind_double(stmt3,,i * 1.0);
sqlite3_bind_text(stmt3,,strData,strlen(strData),SQLITE_TRANSIENT);
if (sqlite3_step(stmt3) != SQLITE_DONE) {
sqlite3_finalize(stmt3);
sqlite3_close(conn);
return;
}
//重新初始化该sqlite3_stmt对象绑定的变量。
sqlite3_reset(stmt3);
printf("Insert Succeed.\n");
}
sqlite3_finalize(stmt3);
//8. 提交之前的事物。
const char* commitSQL = "COMMIT";
sqlite3_stmt* stmt4 = NULL;
if (sqlite3_prepare_v2(conn,commitSQL,strlen(commitSQL),&stmt4,NULL) != SQLITE_OK) {
if (stmt4)
sqlite3_finalize(stmt4);
sqlite3_close(conn);
return;
}
if (sqlite3_step(stmt4) != SQLITE_DONE) {
sqlite3_finalize(stmt4);
sqlite3_close(conn);
return;
}
sqlite3_finalize(stmt4);
//9. 为了方便下一次测试运行,我们这里需要删除该函数创建的数据表,否则在下次运行时将无法创建该表,因为它已经存在。
const char* dropSQL = "DROP TABLE TESTTABLE";
sqlite3_stmt* stmt5 = NULL;
if (sqlite3_prepare_v2(conn,dropSQL,strlen(dropSQL),&stmt5,NULL) != SQLITE_OK) {
if (stmt5)
sqlite3_finalize(stmt5);
sqlite3_close(conn);
return;
}
if (sqlite3_step(stmt5) == SQLITE_DONE) {
printf("The test table has been dropped.\n");
}
sqlite3_finalize(stmt5);
sqlite3_close(conn);
}
int main()
{
doTest();
;
}
//输出结果如下:
//Succeed to create test table now.
//Insert Succeed.
//Insert Succeed.
//Insert Succeed.
//Insert Succeed.
//Insert Succeed.
//Insert Succeed.
//Insert Succeed.
//Insert Succeed.
//Insert Succeed.
//Insert Succeed.
//The test table has been dropped.
该结果和上一个例子(普通数据插入)的结果完全相同,只是在执行效率上明显优于前者。
四、数据查询
数据查询是每个关系型数据库都会提供的最基本功能,下面的代码示例将给出如何通过SQLite API获取数据。
1). 创建测试数据表。
2). 插入一条测试数据到该数据表以便于后面的查询。
3). 执行SELECT语句检索数据。
4). 删除测试表。
见以下示例代码和关键性注释:
#include <sqlite3.h>
#include <string>
#include <stdio.h>
using namespace std;
void doTest()
{
sqlite3* conn = NULL;
//1. 打开数据库
int result = sqlite3_open("D:/mytest.db",&conn);
if (result != SQLITE_OK) {
sqlite3_close(conn);
return;
}
const char* createTableSQL =
"CREATE TABLE TESTTABLE (int_col INT, float_col REAL, string_col TEXT)";
sqlite3_stmt* stmt = NULL;
int len = strlen(createTableSQL);
//2. 准备创建数据表,如果创建失败,需要用sqlite3_finalize释放sqlite3_stmt对象,以防止内存泄露。
if (sqlite3_prepare_v2(conn,createTableSQL,len,&stmt,NULL) != SQLITE_OK) {
if (stmt)
sqlite3_finalize(stmt);
sqlite3_close(conn);
return;
}
//3. 通过sqlite3_step命令执行创建表的语句。对于DDL和DML语句而言,sqlite3_step执行正确的返回值只有SQLITE_DONE。
//对于SELECT查询而言,如果有数据返回SQLITE_ROW,当到达结果集末尾时则返回SQLITE_DONE。
if (sqlite3_step(stmt) != SQLITE_DONE) {
sqlite3_finalize(stmt);
sqlite3_close(conn);
return;
}
//4. 释放创建表语句对象的资源。
sqlite3_finalize(stmt);
printf("Succeed to create test table now.\n");
//5. 为后面的查询操作插入测试数据。
sqlite3_stmt* stmt2 = NULL;
const char* insertSQL = "INSERT INTO TESTTABLE VALUES(20,21.0,'this is a test.')";
if (sqlite3_prepare_v2(conn,insertSQL,strlen(insertSQL),&stmt2,NULL) != SQLITE_OK) {
if (stmt2)
sqlite3_finalize(stmt2);
sqlite3_close(conn);
return;
}
if (sqlite3_step(stmt2) != SQLITE_DONE) {
sqlite3_finalize(stmt2);
sqlite3_close(conn);
return;
}
printf("Succeed to insert test data.\n");
sqlite3_finalize(stmt2);
//6. 执行SELECT语句查询数据。
const char* selectSQL = "SELECT * FROM TESTTABLE";
sqlite3_stmt* stmt3 = NULL;
if (sqlite3_prepare_v2(conn,selectSQL,strlen(selectSQL),&stmt3,NULL) != SQLITE_OK) {
if (stmt3)
sqlite3_finalize(stmt3);
sqlite3_close(conn);
return;
}
int fieldCount = sqlite3_column_count(stmt3);
do {
int r = sqlite3_step(stmt3);
if (r == SQLITE_ROW) {
; i < fieldCount; ++i) {
//这里需要先判断当前记录当前字段的类型,再根据返回的类型使用不同的API函数
//获取实际的数据值。
int vtype = sqlite3_column_type(stmt3,i);
if (vtype == SQLITE_INTEGER) {
int v = sqlite3_column_int(stmt3,i);
printf("The INTEGER value is %d.\n",v);
} else if (vtype == SQLITE_FLOAT) {
double v = sqlite3_column_double(stmt3,i);
printf("The DOUBLE value is %f.\n",v);
} else if (vtype == SQLITE_TEXT) {
const char* v = (const char*)sqlite3_column_text(stmt3,i);
printf("The TEXT value is %s.\n",v);
} else if (vtype == SQLITE_NULL) {
printf("This value is NULL.\n");
}
}
} else if (r == SQLITE_DONE) {
printf("Select Finished.\n");
break;
} else {
printf("Failed to SELECT.\n");
sqlite3_finalize(stmt3);
sqlite3_close(conn);
return;
}
} while (true);
sqlite3_finalize(stmt3);
//7. 为了方便下一次测试运行,我们这里需要删除该函数创建的数据表,否则在下次运行时将无法创建该表,因为它已经存在。
const char* dropSQL = "DROP TABLE TESTTABLE";
sqlite3_stmt* stmt4 = NULL;
if (sqlite3_prepare_v2(conn,dropSQL,strlen(dropSQL),&stmt4,NULL) != SQLITE_OK) {
if (stmt4)
sqlite3_finalize(stmt4);
sqlite3_close(conn);
return;
}
if (sqlite3_step(stmt4) == SQLITE_DONE) {
printf("The test table has been dropped.\n");
}
sqlite3_finalize(stmt4);
sqlite3_close(conn);
}
int main()
{
doTest();
;
}
//输出结果如下:
//Succeed to create test table now.
//Succeed to insert test data.
//The INTEGER value is 20.
//The DOUBLE value is 21.000000.
//The TEXT value is this is a test..
//Select Finished.
//The test table has been dropped.
SQLite应用之实例代码的更多相关文章
- SQLite学习手册(实例代码<一>)
一.获取表的Schema信息: 1). 动态创建表. 2). 根据sqlite3提供的API,获取表字段的信息,如字段数量以及每个字段的类型. 3). 删除该表. ...
- C++11 变长模版和完美转发实例代码
C++11 变长模版和完美转发实例代码 #include <memory>#include <iostream>#include <vector>#include ...
- PHP读取超大文件的实例代码
数据量大带来的问题就是单个文件很大,能够打开这个文件相当不容易,记事本就不要指望了,果断死机 去年年底的各种网站帐号信息的数据库泄漏,很是给力啊,趁机也下载了几个数据库,准备学学数据分析家来分析一 ...
- python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息,抓取政府网新闻内容
python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息PySpider:一个国人编写的强大的网络爬虫系统并带有强大的WebUI,采用Python语言编写 ...
- python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例
python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例 新浪爱彩双色球开奖数据URL:http://zst.aicai.com/ssq/openInfo/ 最终输出结果格 ...
- junit基础篇、中级篇-实例代码
学习文章: http://blog.csdn.net/andycpp/article/details/1327147 http://wenku.baidu.com/link?url=C27gDEj0l ...
- C#开发中使用Npoi操作excel实例代码
C#开发中使用Npoi操作excel实例代码 出处:西西整理 作者:西西 日期:2012/11/16 9:35:50 [大 中 小] 评论: 0 | 我要发表看法 Npoi 是什么? 1.整个Exce ...
- seo之google rich-snippets丰富网页摘要结构化数据(微数据)实例代码
seo之google rich-snippets丰富网页摘要结构化数据(微数据)实例代码 网页摘要是搜索引擎搜索结果下的几行字,用户能通过网页摘要迅速了解到网页的大概内容,传统的摘要是纯文字摘要,而结 ...
- 后台接受ajax传递值的实例代码
后台接受ajax传递值的实例代码: 使用ajax可以实现无刷新数据交互,下面是一段后台代码接收ajax传递值的实例代码供需要的朋友参考,希望能够带来帮助. ajax代码如下: $(function ( ...
随机推荐
- [JS]笔记13之Date对象
-->获取与设置时间的方法-->使用Date对象制作相应的效果 1.设置时间创建一个时间对象 new Date(time); 设置时间 time 从1970年1月1日至几种格式:new D ...
- Hui之Hui.js 官方文档
基础 // 判断值是否是指定数据类型 var result = hui.isTargetType("百签软件", "string"); //=>true ...
- jquery中 $(document).ready()和window.onload的区别
1.执行时间 window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行. $(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕. 2.编写个数不同 ...
- 初识JQuery
轻量级的js库 兼容各种浏览器+css3 传统:js+DHTM jq:解放了客户端的编程, 环境搭建 进入官方网站获取最新的版本 http://jquery.com/download/ ,这里需 ...
- 2016第16本:TED演讲的秘密
花0.01元抢购了<得到APP>中的<成甲说书:TED演讲的秘密>,不到30分钟的音频,感觉全是干货,基本不用看原书了.如果在以后的演讲中随便应用几条都可以让演讲水平提升一大截 ...
- 全文检索引擎 Solr 部署与基本原理
全文检索引擎 Solr 部署与基本原理 搜索引擎Solr环境搭建实例 关于 solr , schema.xml 的配置说明 全文检索引擎Solr系列-–全文检索基本原理 一.搜索引擎Solr环境搭建实 ...
- CSS3-02 样式 1
概述 上一篇博客中,概述了如何在 HTML 文档中使用 CSS,以及如何选择 HTML 元素,并且在文档的最后以表格的形式给出了 CSS 中所有的属性.在接下来的这篇博客中,将阐述主要 HTML 元素 ...
- vim 使用 YouCompleteMe
当然前提是先装好vundle 1 在vimrv中加入Bundle 'Valloric/YouCompleteMe' 2 vim +PluginInstall +qall 3 安装一对底层需要的编译的东 ...
- 【从零开始学习Hadoop】--2.HDFS分布式文件系统
1. 文件系统从头说2. Hadoop的文件系统3. 如何将文件复制到HDFS3.1 目录和文件结构3.2 FileCopy.java文件的源代码3.3 编译3.4打包3.5 运行3.6 检查结果 1 ...
- Undefined class constant 'MYSQL_ATTR_INIT_COMMAND'
新下载的php3.23,本地访问数据库可以,服务器上不行.如下: :( Undefined class constant 'MYSQL_ATTR_INIT_COMMAND' 错误位置 FILE: /u ...