基于C API的SQLite3基本数据库操作

SQLite是一款开源嵌入式文件型数据库,这个主要是和其他一些C/S架构的关系型数据库比较而来的,比如MySQL等。

说他是嵌入式,因为SQLite的所有功能全部包装在一个dll中,我们只需要使用其中的导出接口就可以操作SQLite数据库,这样使得数据存储功能能够很方便的集成进用户的程序中,并运行在客户程序的进程空间中

说他是文件型,因为SQLite的数据库文件就是一个独立文件(SQLite本身不限制数据库文件的扩展名),再没有其他的了,数据,表结构,查询,视图等等都保存在这个数据库文件中,不会依赖任何数据库环境

SQLite的主要特点:
1。无需部署,0配置,无服务端
2。跨平台
2。数据文件管理方便
3。较完善的SQL92标准支持,SQLite基本实现了SQL92标准,其他的一些不兼容的地方,可以参看官方相关说明,链接:
http://www.sqlite.org/omitted.html
4。SQL语句执行速度快,具体的对比数据,网上的评测有很多,这里就不多说了
5。应用较广。最著名的集成应该数Android了吧,其他的PHP ,Python等都做了集成,所以还是很不错的
6。完美的Unicode编码支持。SQLite的接口中,凡是涉及字符串的都是用UTF8或UTF16编码交互,有的同时提供这两种编码的接口函数,所以多语种支持绝对不是问题(这也是我偏爱SQLite的很重要的原因,呵呵)。

好了,下面说说基于C API的SQLite操作,这里谢绝讨论其他的一些包装库,这不是本文的范围,当然SQLite的接口包装库函数还是很多的,基本覆盖各种主流开发语言。如基于Object Pascal的sqlitesimpledelphi,想了解这个库的朋友可以查看我的其他博文:
Delphi 2010下使用sqlitesimpledelphi连接SQLite数据库及中文乱码问题的解决
http://hi.baidu.com/2356/blog/item/4a5549366d94afd6a3cc2bc7.html
sqlitesimpledelphi修正以支持Unicode,Delphi 2010 测试通过
http://hi.baidu.com/2356/blog/item/236ceb2455f2520c4c088db2.html

SQLite的数据库操作其实和常规的数据库操作流程是一样的:
1。连接数据库。
2。构造SQL语句并执行
3。对于SELECT语句,可以获取查询结果
4。数据库使用完毕之后,关闭数据库

这里说明一下,下面所介绍的函数不会涵盖所有的API函数,毕竟SQLite针对同一个功能点提供了不同的API函数,主要表现在参数和配置功能上,有需要深入了解的朋友可以参考官方的文档。

1。打开数据库
API函数:
int sqlite3_open(
const char *filename,   /* 数据库文件路径(UTF-8编码) */
sqlite3 **ppDb          /* 输出: SQLite 数据库句柄 */
);
int sqlite3_open16(
const void *filename,   /* 数据库文件路径(UTF-16) */
sqlite3 **ppDb          /* 输出: SQLite 数据库句柄 */
);
如果调用成功会返回SQLITE_OK,否则返回错误码。

2。构造SQL语句,这里就不多说了,这和SQLite本身无关,可以根据需要使用适当的方法构造即可,注意传给SQLite函数的时候,字符串编码要记得转换为UTF8/UTF16

3。执行SQL语句。
在SQLite中执行SQL语句比较简单的方法是调用函数:
int sqlite3_exec(
sqlite3*,                                  /* 打开的数据库句柄 */
const char *sql,                           /* UTF8编码的SQL语句 */
int (*callback)(void*,int,char**,char**), /* 回调函数,对于SELECT语句返回的结果处理在回调函数中进行 */
void *,                                    /* 传递给回调函数的参数 */
char **errmsg                              /* 相关错误信息 */
);

其实sqlite3_exec只是封装了sqlite3_prepare、sqite3_step(即SQL中的预编译技术)的,主要目的是为使用者提供方便,笔者个人觉得使用后者会更加好一点,这里先做一下总结:

int sqlite3_prepare(
sqlite3 *db,            /* 打开的数据库句柄 */
const char *zSql,       /* UTF8编码的SQL语句,可以参数化 */
int nByte,              /* SQL语句的字节长度,可以传递-1,即字符串以\0结尾 */
sqlite3_stmt **ppStmt, /* 输出:预编译之后的SQL语句句柄 */
const char **pzTail     /* 输出: 指向zSql缓冲区中跳过有效SQL字符串的第一个字节 */
);

int sqlite3_prepare_v2(
sqlite3 *db,            /* 打开的数据库句柄 */
const char *zSql,       /* UTF8编码的SQL语句,可以参数化 */
int nByte,              /* SQL语句的字节长度,可以传递-1,即字符串以宽字符\0结尾 */
sqlite3_stmt **ppStmt, /* 输出: 预编译之后的SQL语句句柄 */
const char **pzTail     /* 输出: 指向zSql缓冲区中跳过有效SQL字符串的第一个字节 */
);

int sqlite3_prepare16(
sqlite3 *db,            /* 打开的数据库句柄 */
const void *zSql,       /* UTF16编码的SQL语句,可以参数化 */
int nByte,              /* SQL语句的字节长度,可以传递-1,即字符串以宽字符\0结尾 */
sqlite3_stmt **ppStmt, /* 输出: 预编译之后的SQL语句句柄 */
const void **pzTail     /* 输出: 指向zSql缓冲区中跳过有效SQL字符串的第一个字节 */
);

int sqlite3_prepare16_v2(
sqlite3 *db,            /* 打开的数据库句柄 */
const void *zSql,       /* UTF16编码的SQL语句,可以参数化 */
int nByte,              /* SQL语句的字节长度,可以传递-1,即字符串以宽字符\0结尾 */
sqlite3_stmt **ppStmt, /* 输出: 预编译之后的SQL语句句柄 */
const void **pzTail     /* 输出: 指向zSql缓冲区中跳过有效SQL字符串的第一个字节 */
);

其中带参数的SQL语句可以这样定义参数:

?NNN 
:VVV 
@VVV 
$VVV 
参数编号从1开始,例如:INSERT into db values(?1, ?2)

v2版本函数时SQLite根据需要添加的增强函数,新的程序推荐使用v2版本函数,只需与原来函数的区别,可以参考官方原文

int sqlite3_step(sqlite3_stmt*);
执行一次预编译SQL语句,在这之前,如果SQL是参数化的,可以调用sqlite3_bind来绑定数据,int、string、blob等等
如果执行成功会返回SQLITE_DONE,如果查询有结果会返回SQLITE_ROW,并可以通过API获取结果中的第一行数据,需要获取下一行数据可以再次调用sqlite3_step直到返回SQLITE_DONE表示后面没有数据了
如果需要重新对预编译的SQL绑定数据并执行,需要先reset一下,然后再调用step,即函数:
int sqlite3_reset(sqlite3_stmt *pStmt);

下面是绑定数据到预编译SQL语句的相关函数:
以下函数的第一个参数指代预编译的SQL句柄,第二个参数指代绑定的参数编号,对应于参数化的SQL语句中的参数编号:

int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
该函数用于绑定二进制数据BLOB,其中最后一个参数是一个回调函数,当成功绑定数据后,会被调用,一般用于自动释放对应的缓冲区

int sqlite3_bind_double(sqlite3_stmt*, int, double);
该函数绑定double浮点数

int sqlite3_bind_int(sqlite3_stmt*, int, int);
该函数绑定int整数

int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
该函数用于绑定具有64位长度的整数,对应于C中的long long结构,由于一个int的范围可能无法满足超大数据量的要求,所以SQLite也支持64位整数,毕竟SQLite官方声称SQLite是支持最大2T的数据的

int sqlite3_bind_null(sqlite3_stmt*, int);
该函数绑定一个空数据到指定列

int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
该函数绑定一段字符串,源字符串是UTF8编码的

int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
该函数绑定一段字符串,源字符串是UTF16编码的

int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
该函数绑定以SQLite结构sqlite3_value存储的通用数据,其中sqlite3_value可以是上述的所有类型,此函数不太常用

int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
该函数绑定指定大小的全零BLOB数据

3。获取SQL查询结果
对于SELECT语句,还需要能够获取结果。上面也提到调用sqlite3_step之后,对于有结果的查询会返回第一行结果,这时可以通过API函数获取当前行的指定字段结果:

const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
该函数以BLOB数据格式获取对应列的数据,BOLB长度使用sqlite3_column_bytes获取

int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
该函数可以用于返回BLOB和字符串的字节长度。对于BLOB,两个函数效果是一样的,但是对于字符串sqlite3_column_bytes返回的是UTF8编码的字符串长度,而sqlite3_column_bytes16返回的是UTF16编码的字符串长度,其间会做必要的字符串格式转换

double sqlite3_column_double(sqlite3_stmt*, int iCol);
该函数返回double数据列

int sqlite3_column_int(sqlite3_stmt*, int iCol);
该函数返回int数据列

sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
该函数返回64位整数,即long long数据

const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
该函数返回字符串,其中sqlite3_column_text输出的字符串使用UTF8编码

sqlite3_column_text16使用UTF16编码
int sqlite3_column_type(sqlite3_stmt*, int iCol);
该函数返回对应列的数据类型

sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
该函数以sqlite3_value结构体返回数据

上面是根据列ID来获取对应的列数据的,如果想通过列名称获取列数据,则需要将列名称转换为对应的列ID,可以使用下面的函数:
const char *sqlite3_column_name(sqlite3_stmt*, int N);
const void *sqlite3_column_name16(sqlite3_stmt*, int N);
该函数返回对应列的名称

4。关闭数据库

int sqlite3_close(sqlite3 * db);
使用该函数可以关闭数据库

好了,基本的调用流程就这么些了,看完这篇文章,应该能够完成基本的数据读写操作了,至于其他的高级操作,有兴趣的朋友可以登录SQLite官方网站查看,这里就不在本文多说了。

转载于:https://www.cnblogs.com/hnrainll/archive/2011/09/08/2170492.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/263252.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode—307. 区域和检索 - 数组可修改

307. 区域和检索 - 数组可修改 题目描述: 给你一个数组 nums ,请你完成两类查询。 其中一类查询要求 更新 数组 nums 下标对应的值 另一类查询要求返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和 &#x…

loadrunner利用虚拟IP测试

LoadRunner 使用虚拟IP测试流程 设置虚拟IP地址 首先,load Generator机器必须使用固定的IP,不能使用动态IP 确定网络中不冲突的IP地址 打开:开始-〉程序-〉loadrunner-〉tools-〉ip wizard, 说明:增加新IP选择第一项&a…

33Exchange Server 2010跨站点部署-分支机构邮件从分支机构出

16.6 SH-ROBIN外网邮件从分部出16.6.1 创建SH-ROBIN发送连接器在上海分支机构的集线器上创建一个发送连接器SH-To Internet添加地址空间,并设定成本添加上海分支机构的两台HT创建好上海分支机构的发送连接器16.6.2 SH-ROBIN站的TOM发送邮件给公网CONTOSOCONTOSO的张…

74HC595芯片使用说明

74HC595是具有8位移位寄存器和一个存储器,三态输出功能。 移位寄存器和存储器是分别的时钟。数据在SHcp的上升沿输入,在STcp的上升沿进入的存储寄存器中去。如果两个时钟连在一起,则移位寄存器总是比存储寄存器早一个脉冲。移位寄存器有一个串…

我的设计模式之旅(4)——生成器(建造者)模式Builder

Builder模式也是创建型模式中的一种。主要用来应对构成复杂但构成结构和顺序相对稳定的对象的创建工作。目的是省去在对象发生变化时,需要修改代码中每一处对象创建的地方,应用这种模式,可以在一个复杂对象的内部结构(由许多其他子对象构成的…

LeetCode—309. 最佳买卖股票时机含冷冻期

309. 最佳买卖股票时机含冷冻期 题目描述: 给定一个整数数组prices,其中第 prices[i] 表示第 i 天的股票价格 。​ 设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票&#xff…

display:inline-block的深入理解 转

在使用CSS实现表现的时候,会经常接触到display:inline-block这一属性,无论是初接触Web标准还是接触标准已久的朋友,大都会对这一属性感觉很迷惑和模糊。 display:inline-block 引用:将对象呈递为内联对象,但是对象的内容作为块对象…

innosetup区分正常状态和静默安装状态(通过传递的参数)

命令行运行程序,如: myprogram.exe /abc /bcd 如果我们想获取其中的参数,“/abc”、“/bcd” 1. 直接使用innosetup自带的方法, GetCmdTail() 将所有参数作为一个字符串返回,安装和卸载都适用 注意:如果打…

测试计划排期内容和格式要求,测试邮件回复统一格式

公司最近在做一些测试流程规范,每次项目立项后,需要确认本次项目测试负责人,由测试项目负责人参加完需求评审后,协调资源 给出测试计划排期与对应子模块负责人员到项目经理处。 下面提供给大家一个测试计划排期内容和格式文档 2.测…

LeetCode—剑指 Offer 4、9、26、35、53

剑指 Offer 4. 二维数组中的查找、9. 用两个栈实现队列、26. 树的子结构、35. 复杂链表的复制、53 - I. 在排序数组中查找数字 I 题目描述: [4] 在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺…

关于VerifyError

http://slurp.doc.ic.ac.uk/pubs/observing/linking.htmlhttp://blog.csdn.net/smilingleo?viewmodelist转载于:https://www.cnblogs.com/diyunpeng/archive/2011/08/30/2159108.html

Ubuntu 安装 JDK 问题

2019独角兽企业重金招聘Python工程师标准>>> 1. 下载并解压缩 2. mv到/usr/lib/jdk 3. 在~/.bashrc文件末尾添加环境变量 export JAVA_HOME/usr/lib/jdkexport CLASSPATH${JAVA_HOME}/libexport PATH${JAVA_HOME}/bin:$PATH 4. 重启终端,输入javac -vers…

Asp.net中水晶报表的使用

在我们对VS.Net中的水晶报表(Crystal Reports)进行研究之前,我和我朋友对如何将这个复杂的东东加入我们的Web应用有着非常的好奇心。一周以后,在阅读了大量的“HOWTO”文档之后,我们成功地将一些简单的报告加入到了我们…

Html颜色值 to RGB

//Html颜色值转换为RGBfunction HhtmlColorToRGB(color){var str"0x" color.substring(1,color.length);var rstr&0x0000FF;var g(str&0x00FF00)>>8;var b(str&0xFF0000)>>16;return b "," g "," r;}转载于:https:…

LeetCode—剑指 Offer 32 - I、II、III. 从上到下打印二叉树

剑指 Offer 32. 从上到下打印二叉树 题目描述: 使用层序遍历,遍历二叉树的三种题目。 [I] 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。 [II] 从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印…

2011-8-31 身体欠佳

1. 前几日明显感到身体欠佳,熬夜很难受,以往搞到1点问题不大的, 老了啊。 经过几天作息时间的调整,回家不开电脑,23点之前上床,在加上食疗,今天缓过来了。 看来有必要把生活节奏放慢一点&#x…

java方法的定义格式

Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段,声明格式为: [修饰符1 修饰符2 …..] 返回值类型 方法名( 形式参数列表 ){ Java 语句;… … … } 例如 public static int add(int a,int b){ int sumab; return sum; } 语法解释&a…

Scala学习(一)--Scala基础学习

Scala基础学习 摘要: 在篇主要内容:如何把Scala当做工业级的便携计算器使用,如何用Scala处理数字以及其他算术操作。在这个过程中,我们将介绍一系列重要的Scala概念和惯用法。同时你还将学到作为初学者如何浏览Scaladoc文档 1. 使…

Test live writer

拷贝屏幕来的图片 转载于:https://www.cnblogs.com/huobazi/archive/2006/11/19/565070.html

LeetCode—剑指 Offer 10 - I、II 斐波那契数列、青蛙跳台阶问题 63. 股票的最大利润

剑指 Offer 10 - I、II 斐波那契数列、青蛙跳台阶问题 63. 股票的最大利润 题目描述: [I] 斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。答案需要取模 1e97(1000000007),如计算初始结果为…