C++网络编程(四)轻量级数据库sqlite3

C++网络编程(四)轻量级数据库sqlite3

前言

这里貌似与网络编程的关联度已经不大,属于可选的分支发展方向,鉴于经常遇见需要数据库的情况,这里对轻量级的数据库sqlite3在C++中的相关调用做简单整理。

sqlite3获取

Windows

首先下载sqlite3的c语言源码
https://www.sqlite.org/2022/sqlite-amalgamation-3400000.zip

windows下的dll文件:
https://www.sqlite.org/2022/sqlite-dll-win64-x64-3400000.zip

MinGW编译器:

将sqlite3.h头文件复制到~\MinGW\x86_64-w64-mingw32\include\目录下。

将sqlite3.dll库文件复制到~\MinGW\lib\目录下。

编译时加上-lsqlite3参数即可。

类似于openGL等库的调用

Linux

wget https://www.sqlite.org/2022/sqlite-autoconf-3400100.tar.gz
tar -zvxf sqlite-autoconf-3400100.tar.gz
cd sqlite-autoconf-3400100
./configure
make
sudo make install

流程如上,获取安装包后解压,进入到解压后的文件开始配置。

make编译过程稍稍较慢,需要耐心等待。

安装成功后可以直接使用sqlite3.h头文件。但是程序的编译过程也要加上-lsqlite3链接参数

C++提供的API

/*创建或者打开数据库
filename: 要打开的数据库文件,不存在则创建
ppdb: 保存打开数据库实例的指针*/
int sqlite3_open(const char *filename, sqlite3 **ppdb);
/*关闭数据库
pdb: 数据库指针*/
int sqlite3_close(sqlite3 *pdb);
int sqlite3_exec(//执行sql命令
    sqlite3 *db,
    const char *sql,
    int(*callback)(void *arg,int num,char **columnvalue,char **columnname),
    void *data,
    char **errmsg);
/*参数
db: 数据库句柄
sql: sql语句
callback: 回调函数,在执行查询操作的时候调用,一行数据调用一次
data: 传递给回调函数第一个参数的指针,可以为NULL
errmsg: 错误信息

回调函数参数: 
arg: sqlite3_exec中的data参数
num: 数据的列数
columnvalue: 数据的内容,字符串形式
columnname: 列名
*/

以上函数执行成功,返回SQLITE_OK(即 0),执行出错,返回错误信息;
SQL语句此处不做整理了

运行优化

性能优化一般是在插入数据的时候,如果是要插入大量数据,而只调用sqlite3_exec函数,效率极其低下。采用-O3编译优化。

显式开启事务

在默认情况下,每一次调用sqlite3_exec函数都要隐式的开启和关闭一次事务,这是极其耗费时间的,一种优化方法是将所有的sql语句放到一个事务中去执行,即显示开启事务,在开始前执行sql命令begin,结束后执行sql命令commit

//默认
string sql1("insert into student values(");
string sql2, sql3(",'aa',20);"), sql4;
for (int i = 0; i < 10000; i++)
{
    sql2 = to_string(i);
    sql4 = sql1 + sql2 + sql3;
    res = sqlite3_exec(db, sql4.c_str(), 0, 0, &zErrMsg);
    if (res != SQLITE_OK)
    {
        cout << zErrMsg << endl;
        break;
    }
}
//显式开启事务
string sql1("insert into student values(");
string sql2, sql3(",'aa',20);"), sql4;
sqlite3_exec(db, "begin;", 0, 0, 0); //显示开启事务
for (int i = 0; i < 10000; i++)
{
    sql2 = to_string(i);
    sql4 = sql1 + sql2 + sql3;
    res = sqlite3_exec(db, sql4.c_str(), 0, 0, &zErrMsg);
    if (res != SQLITE_OK)
    {
        cout << zErrMsg << endl;
        break;
    }
}
sqlite3_exec(db, "commit;", 0, 0, 0); //提交事务

事实上,后者比前者速度提高了约1000倍。

执行准备

在插入大量数据时,sql语句存在很多重复操作,这样的语句每一次都会耗费时间用于解析sql语句。我们可以预先将sql语句编译好再执行,每次只改变要插入的数据,这样可以省去较多的解析时间,提高效率。

  1. 调用sqlite3_prepare_v2函数对sql语句进行预编译
int sqlite3_prepare_v2(
	sqlite3 *db,
    const char *zsql,
    int nByte,
    sqlite3_stmt **ppstmt,
    const char **pzTail);
/*
db: 数据库句柄
zsql: SQL语句
nByte: SQL语句的最大长度,字节单位,如果为-1则读取到第一个零终止符,如果为正数则读取字节数,如果为0则不生成语句
ppstmt: 输出编译好的语句句柄
pzTail: 输出指向SQL语句未使用部分的指针
*/
  1. 调用sqlite3_bind函数来绑定数据。
int sqlite3_bind_blob(sqlite3_stmt *,int ,const void *,int ,void(*)(void *));//blob二进制大对象
int sqlite3_bind_double(sqlite3_stmt *,int,double);//double浮点数据
int sqlite3_bind_int(sqlite3_stmt *,int,int);//int整数
int sqlite3_bind_null(sqlite3_stmt *,int);//空值
int sqlite3_bind_text(sqlite3_stmt *,int,const char *,int ,void(*)(void *));//text字符串
/*
应用时,第一个参数用于指明SQL语句
第二个参数用于指明SQL语句中第几个参数,从1开始
第三个参数是值
text第四个参数是字符串长度,第五个参数是字符串析构函数,可为NULL
*/
  1. 调用sqlite3_step来完成一行数据插入
sqlite3_step(sqlite3_stmt *);

在调用sqlite3_step之后记得调用sqlite3_reset用于清除sqlite3_stmt中绑定的数据,因为当下一次调用绑定的时候无法覆盖之前的内容。

sqlite3_reset一般用于绑定数据之前。

//以?代替具体数值
char sql[] = "insert into student values(?,?,?);";
sqlite3_stmt *stmt;
sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, 0);
sqlite3_exec(db, "begin;", 0, 0, 0);
for (int i = 0; i < 1000000; i++)
{
    sqlite3_reset(stmt);
    sqlite3_bind_int(stmt, 1, i);
    sqlite3_bind_text(stmt, 2, "aa", 2, NULL);
    sqlite3_bind_int(stmt, 3, 20);
    sqlite3_step(stmt);
}
sqlite3_exec(db, "commit;", 0, 0, 0);
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

registor11

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值