sqlite3使用简介(内含解决sqlite内存的方法)

一.使用流程

要使用sqlite,需要从sqlite官网下载到三个文件,分别为sqlite3.lib,sqlite3.dll,sqlite3.h,然后再在自己的工程中配置好头文件和库文件,同时将dll文件放到当前目录下,就完成配置可以使用sqlite了。

使用的过程根据使用的函数大致分为如下几个过程:

  • sqlite3_open()
  • sqlite3_prepare()
  • sqlite3_step()
  • sqlite3_column()
  • sqlite3_finalize()
  • sqlite3_close()

这几个过程是概念上的说法,而不完全是程序运行的过程,如sqlite3_column()表示的是对查询获得一行里面的数据的列的各个操作统称,实际上在sqlite中并不存在这个函数。

1.  sqlite3_open():打开数据库

在操作数据库之前,首先要打开数据库。这个函数打开一个sqlite数据库文件的连接并且返回一个数据库连接对象。这个操作同时程序中的第一个调用的 sqlite函数,同时也是其他sqlite api的先决条件。许多的sqlite接口函数都需要一个数据库连接对象的指针作为它们的第一个参数。

函数定义

  const char *filename,   /* Database filename (UTF-8) */

  sqlite3 **ppDb          /* OUT: SQLite db handle */

);

  const void *filename,   /* Database filename (UTF-16) */

  sqlite3 **ppDb          /* OUT: SQLite db handle */

);

  const char *filename,   /* Database filename (UTF-8) */

  sqlite3 **ppDb,         /* OUT: SQLite db handle */

  int flags,              /* Flags */

  const char *zVfs        /* Name of VFS module to use */

);

 

说明:

假如这个要被打开的数据文件不存在,则一个同名的数据库文件将被创建。如果使用sqlite3_open和sqlite3_open_v2的话,数据库将采用UTF-8的编码方式,sqlite3_open16采用UTF-16的编码方式

返回值:

如果sqlite数据库被成功打开(或创建),将会返回SQLITE_OK,否则将会返回错误码。Sqlite3_errmsg()或者sqlite3_errmsg16可以用于获得数据库打开错误码的英文描述,这两个函数定义为:

const char *sqlite3_errmsg(sqlite3*);

const void *sqlite3_errmsg16(sqlite3*);

        

参数说明:

filename:需要被打开的数据库文件的文件名,在sqlite3_open和sqlite3_open_v2中这个参数采用UTF-8编码,而在sqlite3_open16中则采用UTF-16编码

ppDb:一个数据库连接句柄被返回到这个参数,即使发生错误。唯一的一场是如果sqlite不能分配内存来存放sqlite对象,ppDb将会被返回一个NULL值。

flags:作为数据库连接的额外控制的参数,可以是SQLITE_OPEN_READONLY,SQLITE_OPEN_READWRITE和 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE中的一个,用于控制数据库的打开方式,可以和SQLITE_OPEN_NOMUTEX,SQLITE_OPEN_FULLMUTEX, SQLITE_OPEN_SHAREDCACHE,以及SQLITE_OPEN_PRIVATECACHE结合使用,具体的详细情况可以查阅文档

 

 

 

 

2.  Sqlite3_prepare()

这个函数将sql文本转换成一个准备语句(prepared statement)对象,同时返回这个对象的指针。这个接口需要一个数据库连接指针以及一个要准备的包含SQL语句的文本。它实际上并不执行(evaluate)这个SQL语句,它仅仅为执行准备这个sql语句

函数定义(仅列出UTF-8的)

  sqlite3 *db,            /* Database handle */

  const char *zSql,       /* SQL statement, UTF-8 encoded */

  int nByte,              /* Maximum length of zSql in bytes. */

  sqlite3_stmt **ppStmt,  /* OUT: Statement handle */

  const char **pzTail     /* OUT: Pointer to unused portion of zSql */

);

  sqlite3 *db,            /* Database handle */

  const char *zSql,       /* SQL statement, UTF-8 encoded */

  int nByte,              /* Maximum length of zSql in bytes. */

  sqlite3_stmt **ppStmt,  /* OUT: Statement handle */

  const char **pzTail     /* OUT: Pointer to unused portion of zSql */

);

 

参数:

db:数据指针

zSql:sql语句,使用UTF-8编码

nByte:如果nByte小于0,则函数取出zSql中从开始到第一个0终止符的内容;如果nByte不是负的,那么它就是这个函数能从zSql中读取的字节数的最大值。如果nBytes非负,zSql在第一次遇见’/000/或’u000’的时候终止

pzTail:上面提到zSql在遇见终止符或者是达到设定的nByte之后结束,假如zSql还有剩余的内容,那么这些剩余的内容被存放到pZTail中,不包括终止符

ppStmt:能够使用sqlite3_step()执行的编译好的准备语句的指针,如果错误发生,它被置为NULL,如假如输入的文本不包括sql语句。调用过程必须负责在编译好的sql语句完成使用后使用sqlite3_finalize()删除它。

 

说明

如果执行成功,则返回SQLITE_OK,否则返回一个错误码。推荐在现在任何的程序中都使用sqlite3_prepare_v2这个函数,sqlite3_prepare只是用于前向兼容

 

备注

<1>准备语句(prepared statement)对象

typedef struct sqlite3_stmt sqlite3_stmt;

        

准备语句(prepared statement)对象一个代表一个简单SQL语句对象的实例,这个对象通常被称为“准备语句”或者“编译好的SQL语句”或者就直接称为“语句”。

         语句对象的生命周期经历这样的过程:

l  使用sqlite3_prepare_v2或相关的函数创建这个对象

l  使用sqlite3_bind_*()给宿主参数(host parameters)绑定值

l  通过调用sqlite3_step一次或多次来执行这个sql

l  使用sqlite3——reset()重置这个语句,然后回到第2步,这个过程做0次或多次

l  使用sqlite3_finalize()销毁这个对象

 

在sqlite中并没有定义sqlite3_stmt这个结构的具体内容,它只是一个抽象类型,在使用过程中一般以它的指针进行操作,而sqlite3_stmt类型的指针在实际上是一个指向Vdbe的结构体得指针

<2>宿主参数(host parameters)

在传给sqlite3_prepare_v2()的sql的语句文本或者它的变量中,满足如下模板的文字将被替换成一个参数:

l  ?

l  ?NNN,NNN代表数字

l  :VVV,VVV代表字符

l  @VVV

l  $VVV

在上面这些模板中,NNN代表一个数字,VVV代表一个字母数字标记符(例如:222表示名称为222的标记符),sql语句中的参数(变量)通过上面的几个模板来指定,如

“select ? from ? “这个语句中指定了两个参数,sqlite语句中的第一个参数的索引值是1,这就知道这个语句中的两个参数的索引分别为1和2,使用”?”的话会被自动给 予索引值,而使用”?NNN”则可以自己指定参数的索引值,它表示这个参数的索引值为NNN。”:VVV”表示一个名为”VVV”的参数,它也有一个索引 值,被自动指定。

可以使用sqlite3_bind_*()来给这些参数绑定值

 

 

 

3.  sqlite3_setp()

这个过程用于执行有前面sqlite3_prepare创建的准备语句。这个语句执行到结果的第一行可用的位置。继续前进到结果的第二行的话,只需再次调 用sqlite3_setp()。继续调用sqlite3_setp()知道这个语句完成,那些不返回结果的语句(如:INSERT,UPDATE,或 DELETE),sqlite3_step()只执行一次就返回

函数定义

int sqlite3_step(sqlite3_stmt*);

返回值

函数的返回值基于创建sqlite3_stmt参数所使用的函数,假如是使用老版本的接口sqlite3_prepare()和 sqlite3_prepare16(),返回值会 是 SQLITE_BUSY, SQLITE_DONE, SQLITE_ROW, SQLITE_ERROR 或 SQLITE_MISUSE,而v2版本的接口sqlite3_prepare_v2()和sqlite3_prepare16_v2()则会同时返 回这些结果码和扩展结果码。

对所有V3.6.23.1以及其前面的所有版本,需要在sqlite3_step()之后调用sqlite3_reset(),在后续的sqlite3_ step之前。如果调用sqlite3_reset重置准备语句失败,将会导致sqlite3_ step返回SQLITE_MISUSE,但是在V3. 6.23.1以后,sqlite3_step()将会自动调用sqlite3_reset。

int sqlite3_reset(sqlite3_stmt *pStmt);

sqlite3_reset用于重置一个准备语句对象到它的初始状态,然后准备被重新执行。所有sql语句变量使用sqlite3_bind*绑定值,使 用sqlite3_clear_bindings重设这些绑定。Sqlite3_reset接口重置准备语句到它代码开始的时候。sqlite3_reset并不改变在准备语句上的任何绑定值,那么这里猜测,可能是语句在被执行的过程中发生了其他的改变,然后这个语句将它重置到绑定值的时候的那个状态。

 

4.  sqlite3_column()

这个过程从执行sqlite3_step()执行一个准备语句得到的结果集的当前行中返回一个列。每次sqlite3_step得到一个结果集的列停下后,这个过程就可以被多次调用去查询这个行的各列的值。对列操作是有多个函数,均以sqlite3_column为前缀

const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);

int sqlite3_column_bytes(sqlite3_stmt*, int iCol);

int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);

double sqlite3_column_double(sqlite3_stmt*, int iCol);

int sqlite3_column_int(sqlite3_stmt*, int iCol);

sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);

const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);

const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);

int sqlite3_column_type(sqlite3_stmt*, int iCol);

sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);

说明

第一个参数为从sqlite3_prepare返回来的prepared statement对象的指针,第二参数指定这一行中的想要被返回的列的索引。最左边的一列的索引号是0,行的列数可以使用sqlite3_colum_count()获得。

这些过程会根据情况去转换数值的类型,sqlite内部使用sqlite3_snprintf()去自动进行这个转换,下面是关于转换的细节表:

内部类型

请求的类型

转换

NULL

INTEGER

结果是0

NULL

FLOAT

结果是0.0

NULL

TEXT

结果是NULL

NULL

BLOB

结果是NULL

INTEGER

FLOAT

从整形转换到浮点型

INTEGER

TEXT

整形的ASCII码显示

INTEGER

BLOB

同上

FLOAT

INTEGER

浮点型转换到整形

FLOAT

TEXT

浮点型的ASCII显示

FLOAT

BLOB

同上

TEXT

INTEGER

使用atoi()

TEXT

FLOAT

使用atof()

TEXT

BLOB

没有转换

BLOB

INTEGER

先到TEXT,然后使用atoi

BLOB

FLOAT

先到TEXT,然后使用atof

BLOB

TEXT

如果需要的话添加0终止符

 

注:BLOB数据类型是指二进制的数据块,比如要在数据库中存放一张图片,这张图片就会以二进制形式存放,在sqlite中对应的数据类型就是BLOB

 

int sqlite3_column_bytes(sqlite3_stmt*, int iCol)int sqlite3_column_bytes16(sqlite3_stmt*, int iCol)两个函数返回对应列的内容的字节数,这个字节数不包括后面类型转换过程中加上的0终止符。

下面是几个最安全和最简单的使用策略

  • 先sqlite3_column_text() ,然后 sqlite3_column_bytes()
  • 先sqlite3_column_blob(),然后sqlite3_column_bytes()
  • 先sqlite3_column_text16(),然后sqlite3_column_bytes16()

 

 

5.  sqlite3_finalize

    int sqlite3_finalize(sqlite3_stmt *pStmt);

这个过程销毁前面被sqlite3_prepare创建的准备语句,每个准备语句都必须使用这个函数去销毁以防止内存泄露。

在空指针上调用这个函数没有什么影响,同时可以准备语句的生命周期的任一时刻调用这个函数:在语句被执行前,一次或多次调用sqlite_reset之后,或者在sqlite3_step任何调用之后不管语句是否完成执行

 

6.  sqlite3_close

这个过程关闭前面使用sqlite3_open打开的数据库连接,任何与这个连接相关的准备语句必须在调用这个关闭函数之前被释放

 

 

二.使用举例

 

?
#include "stdafx.h"
#include "sqlite3.h"
static int callback(void *NotUsed, int argc, char **argv, char **azColName)
{
    int i;
    for(i=0; i<argc; i++){
       printf("%s = %s/n", azColName[i], argv[i] ? argv[i] : "NULL");
    }
    printf("/n");
    return 0;
}
#define CHECK_RC(rc,szInfo,szErrMsg,db) if(rc!=SQLITE_OK) /
           {printf("%s error!/n",szInfo);/
           printf("%s/n",szErrMsg);    /
           sqlite3_free(szErrMsg);         /
           sqlite3_close(db);              /
           return 0;}
int _tmain(int argc, _TCHAR* argv[])
{
  
    sqlite3 *db;
    char *dbPath="f:/test.db";
    char *szErrMsg = 0;
  
    int rc= sqlite3_open(dbPath, &db);
    CHECK_RC(rc,"open database",db);
    char *szSql="create table UserInfo(ID int primary key , UserName char, PassWord char);";
    rc=sqlite3_exec(db,szSql,0,0,&szErrMsg);
    CHECK_RC(rc,"create table",szErrMsg,db);
    rc=sqlite3_exec(db,"insert into UserInfo(ID,UserName,PassWord) values(1,'kfqcome','123456')",0,0,&szErrMsg);
    CHECK_RC(rc,"insert info",szErrMsg,db);
    rc=sqlite3_exec(db,"insert into UserInfo(ID,UserName,PassWord) values(2,'miss wang','654321')",0,0,&szErrMsg);
    CHECK_RC(rc,"insert info",szErrMsg,db);
    szSql="select * from UserInfo";
    rc = sqlite3_exec(db,szSql, callback, 0, &szErrMsg);
    CHECK_RC(rc,"query values",szErrMsg,db);
    sqlite3_close(db);
    getchar();
    return 0;
}

  输出的结果:

ID = 1

UserName = kfqcome

PassWord = 123456

 

ID = 2

UserName = miss wang

PassWord = 654321

 

这里执行sql语句用的是sqlite3_exec,它是前面几个函数的封装

 

int sqlite3_exec(

  sqlite3*,                                  /* An open database */

  const char *sql,                           /* SQL to be evaluated */

  int (*callback)(void*,int,char**,char**),  /* Callback function */

  void *,                                    /* 1st argument to callback */

  char **errmsg                              /* Error msg written here */

);

sqlite3_exec是sqlite3_prepare_v2,sqlite3_step()和sqlite3_finalize()的封装,能让程序多次执行sql语句而不要写许多重复的代码。

Sqlite3_exec接口执行0或多个UTF-8编码的,分号分割的sql语 句,传到第二个参数中。如果sqlite3_exec的第三个参数回调函数指针不为空,那么它会为每个来自执行的SQL语句的结果行调用(也就是说回调函 数会调用多次,上面例子中会返回2个结果行,因而会被执行2次),第4个参数是传给回调函数的第一个参数,如果回调函数指针为空,那么回调不会发生同时结 果行被忽略。

如果在执行sql语句中有错误发生,那么当前的语句的执行被停止,后续的语句也被跳过。第五个参数不为空的时候,它被分配内存并写入了错误信息,所以在sqlite3_exec后面需要调用sqlite3_free去释放这个对象以防止内存泄露

 

转载于:https://www.cnblogs.com/zhoug2020/p/4061071.html

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

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

相关文章

动态更新纹理

1. 创建C类继承自AStaticMeshActor 2. 定义用于渲染队列的数据结构 struct FUpdateTextureData {FTexture2DResource* Texture2DResource;FUpdateTextureRegion2D* UpdateTextureRegion;uint8* DynamicColors;int32 w; }; 3. 增加成员变量 UMaterialInstanceDynamic* mDynam…

阿旺wifi智能系统源码

系统简介本系统适合DD-WRT固件路由器和OoenWrt固件路由器或者任何带有WIFIDOG插件的路由器。系统基于ThinkPHP框架PHPMySQL的技术开发。系统主要功能: 1.无密码认证&#xff1a;只点击按钮或强制看广告1.验证码认证&#xff1a;招待券认证、一次性账号、指定时间限制3.用户名密…

动态更新纹理闪烁问题

1. 模型旋转角度尽量取整数&#xff0c;保证线条不会出现锯齿 2. 修改反锯齿模型为FXAA方式&#xff0c;默认的TemporalAA方式会闪烁 3. 动态更新的纹理尺寸一般都不会是2的N次方&#xff0c;比如401X518。 解决方案是 动态更新一张1024x1024的贴图的其中401X518&#xff0c;…

warning C4828问题的处理

warning C4828: 文件包含在偏移 0x215 处开始的字符&#xff0c;该字符在当前源字符集中无效(代码页 65001)。 (编译源文件 XXXXXXcpp) 这提示是由于字符集的问题导致&#xff0c;解决方案如下 点击VS2017 文件->另存为->编码保存->65001 然后重新编译,警告问题解决…

OC中description、 SEL、类本质、self和super用法

一&#xff1a;description方法 description有对象方法和类方法两种&#xff0c;&#xff08;是NSObject类的方法&#xff09;1&#xff0c;-description&#xff08;对象方法&#xff09; 使用NSLog和%输出某个对象时&#xff0c;会调用对象的description方法&#xff0c;并拿…

修改场景默认pawn的方法

playstart方法 1. 放置playstart到场景中 2. 修改world settings的GameMode 直接放置pawn方法 1. 放置pawn到场景中 2. 修改world settings的GameMode 3. 修改pawn的Auto Possess Player为Player 0

lecture3-线性神经元和算法

Hinton第三课 这节课主要是介绍NN的输出端常用的神经元&#xff0c;然后重点是说明怎么使用BP来计算偏导数&#xff0c;在Hinton这一课中&#xff0c;他提供了他1986年参与写的《并行分布处理》一书的第8章&#xff0c;49页&#xff0c;这本书的编者是当你的认知神经界的Rumelh…

ubuntu开机出现错误“Error found when loading /root/.profile”解决

在刚修改完root权限自动登录后&#xff0c;发现开机出现以下提示&#xff1a; Error found when loading /root/.profile stdin:is not a tty 解决方法&#xff1a;在终端中用命令gedit /root/.profile&#xff0c;打开文件后找到“mesg n”&#xff0c; 将其更改为“tty -s …

DropBox 超实用的免费文件网络同步、备份、分享工具

http://www.iplaysoft.com/dropbox.html DropBox 就是一款非常好用的免费网络文件同步工具(当然它也算是一个服务)。当你在电脑A使用DropBox时&#xff0c;指定文件夹里所有文件的改动均会自动地“同步”到DropBox的服务器&#xff0c;当下次你在电脑B需要使用这些文件时&#…

8个有趣的Linux提示与技巧

我们时不时给你带来关于Linux的提示与技巧。这里我们总结了8个最有趣的提示和技巧。推荐学习Linux视频教程。 以它们的大小列出文件如果你想要一个基于它们大小排序的文件列表&#xff0c;你可以使用下面的命令。它会以递减顺序排列文件。# ls -l | grep ^- | sort -nr -k 5 | …

Ubuntu 14.04 文件服务器--samba的安装和配置

samba是Linux系统上的一种文件共享协议&#xff0c;可以实现Windows系统访问Linux系统上的共享资源&#xff0c;现在介绍一下如何在Ubuntu 14.04上安装和配置samba一、 一、更新源列表 打开"终端窗口"&#xff0c;输入"sudo apt-get update"-->回车--…

export LD_LIBRARY_PATH 的使用

对linux不是很熟&#xff0c;之前只是听说过可以设置程序共享库位置也就是 使用 “export LD_LIBRARY_PATH” 今天用了用&#xff0c;感觉还挺不错&#xff0c;也很常用。 比如你编译了一个so 而这个so 同时又依赖其他第三方库。如果你想把你编译的so 提供给别人用的话&#…

MongoDB命令及SQL语法对比

mongodb与mysql命令对比 传统的关系数据库一般由数据库&#xff08;database&#xff09;、表&#xff08;table&#xff09;、记录&#xff08;record&#xff09;三个层次概念组成&#xff0c;MongoDB是由数据库&#xff08;database&#xff09;、集合&#xff08;collectio…

[oracle] 组织架构退格显示 connect by

1. 按组织架构关系退格显示 create or replace view v_vieworg asselect --v.OBJID,v.OBJNAMElevel as levelid, lpad(        ,2*level-2)||v.OBJNAME as OBJNAME,v.OBJID,v.OBJCODE,v.ISDEPT,v.PARENTAREAID,v.PARENTDEPTID,v.ParentID,v.canceledfrom v_organddept …

创建mip纹理链

(1) 我们要做的是&#xff0c;根据原始纹理T0创建一系列的纹理&#xff08;通常使用平均滤波&#xff09;&#xff1a;T1、T2…Tn&#xff0c;其中每个纹理的大小都是前一个纹理的1/4&#xff0c;即长度和宽度减半&#xff0c;如图12.40所示。 要根据前一个mip纹理计算当前纹…

Oracle RAC学习笔记:基本概念及入门

oracle 10g real application clusters introduction 1、什么是cluster一个cluster是由两个或是多个独立的、通过网络连接的servers组成的。几个硬件供应商多年以来提供了Cluster性能的各种需求。一些Clusters仅仅为了提供高可用性的&#xff0c;在当前活动的node发生故障时…

微信公众平台新增语义理解接口

微信公众平台语义理解接口正式对外开放。通过语义接口&#xff0c;接收用户发送的自然语言请求&#xff0c;让系统理解用户的说话内容。 微信语义理解接口提供从用户自然语言输入到结构化解析的技术实现&#xff0c;使用先进的自然语言处理技术给开发者提供一站式的语义解析方案…

Jetty 的工作原理以及与 Tomcat 的比较

http://www.ibm.com/developerworks/cn/java/j-lo-jetty/Jetty 目前的是一个比较被看好的 Servlet 引擎&#xff0c;它的架构比较简单&#xff0c;也是一个可扩展性和非常灵活的应用服务器&#xff0c;它有一个基本数据模型&#xff0c;这个数据模型就是 Handler&#xff0c;所…

最大子图形问题

CODEVS1159最大全0子矩阵 题目描述 Description 在一个0,1方阵中找出其中最大的全0子矩阵&#xff0c;所谓最大是指O的个数最多。思路&#xff1a;这个题最朴素的n^6的算法&#xff0c;超时美美的。。。然后想优化&#xff0c;从一个点向上方、左方、右方扩展&#xff0c;首先更…