SQLiteC/C++接口详细介绍之sqlite3类(十四)

 返回目录:SQLite—免费开源数据库系列文章目录 

上一篇:SQLiteC/C++接口详细介绍之sqlite3类(十三)

下一篇:SQLiteC/C++接口详细介绍之sqlite3类(十五)

43.sqlite3_preupdate_hook

sqlite3_preupdate_hook函数用于注册一个回调函数,当执行UPDATE、INSERT、DELETE操作时,此回调函数会在每一行变更之前被调用。该函数的原型如下:

void sqlite3_preupdate_hook(sqlite3 *db,void *pArg,int iCmd,char const *zDb,char const *zName,sqlite3_int64 arg1,sqlite3_int64 arg2,int arg3
);

该函数的参数说明如下:

- db: 数据库连接句柄。
- pArg: 提供给回调函数使用的用户指针。
- iCmd: 修改命令类型,值为SQLITE_INSERT、SQLITE_UPDATE或SQLITE_DELETE。
- zDb和zName: 数据库名和表名。
- arg1、arg2和arg3: 提供详细信息的附加参数。

下面是一个示例,在执行UPDATE、INSERT、DELETE操作之前,输出被更改的列的值:

#include <sqlite3.h>
#include <stdio.h>
static void preupdate_callback(sqlite3 *db,  // 数据库连接句柄void *pArg,   // 用户指针int iCmd,     // 修改命令类型char const *zDb,  // 数据库名char const *zName, // 表名sqlite3_int64 arg1,  // 行IDsqlite3_int64 arg2,  // 新行IDint arg3             // 列ID
) {if (iCmd == SQLITE_UPDATE) {printf("UPDATE table %s.%s: (id=%lld) %d -> %d\n", zDb, zName, arg1,*((int*)arg2 + arg3), *((int*)arg1 + arg3));} else if (iCmd == SQLITE_INSERT) {printf("INSERT table %s.%s: (id=%lld)\n", zDb, zName, arg1);} else if (iCmd == SQLITE_DELETE) {printf("DELETE table %s.%s: (id=%lld)\n", zDb, zName, arg1);}
}
int main() {sqlite3 *db;sqlite3_open(":memory:", &db);sqlite3_exec(db, "CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)", NULL, NULL, NULL);sqlite3_preupdate_hook(db, preupdate_callback, NULL);sqlite3_exec(db, "INSERT INTO test (id, value) VALUES (1, 'hello')", NULL, NULL, NULL);sqlite3_exec(db, "UPDATE test SET value = 'world' WHERE id = 1", NULL, NULL, NULL);sqlite3_exec(db, "DELETE FROM test WHERE id = 1", NULL, NULL, NULL);sqlite3_close(db);return 0;
}

输出结果为:

INSERT table main.test: (id=1)
UPDATE table main.test: (id=1) hello -> world
DELETE table main.test: (id=1)

44.sqlite3_preupdate_new

sqlite3_preupdate_new函数用于向UPDATE事件中添加一个新的行。通常情况下,UPDATE事件会更新一个已经存在的行,但有时候需要添加一行新的数据,并以此替换原来的行。例如,当更新一行数据时,如果该行数据不存在,有时需要新增一行数据。

该函数的原型如下:

int sqlite3_preupdate_new(sqlite3 *db,int op,const char *zDb,const char *zName,sqlite_int64 iKey
);

该函数的参数说明如下:

- db: 数据库连接句柄。
- op: 操作类型,取值为SQLITE_INSERT或SQLITE_UPDATE。
- zDb和zName: 数据库名和表名。
- iKey: 新行的主键值。

该函数必须在sqlite3_preupdate_hook回调函数中调用,并在调用sqlite3_preupdate_step()之前被调用。下面是一个示例,该示例在UPDATE事件中新增一个行数据:

#include <sqlite3.h>
#include <stdio.h>
static void preupdate_callback(sqlite3 *db,  // 数据库连接句柄void *pArg,   // 用户指针int iCmd,     // 修改命令类型char const *zDb,  // 数据库名char const *zName, // 表名sqlite3_int64 arg1,  // 行IDsqlite3_int64 arg2,  // 新行IDint arg3             // 列ID
) {if (iCmd == SQLITE_UPDATE) {const char *value = "new value";sqlite3_preupdate_new(db, SQLITE_INSERT, zDb, zName, arg2);sqlite3_preupdate_set(db, value);sqlite3_preupdate_column_name(db, "value");}
}
int main() {sqlite3 *db;sqlite3_open(":memory:", &db);sqlite3_exec(db, "CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)", NULL, NULL, NULL);sqlite3_preupdate_hook(db, preupdate_callback, NULL);sqlite3_exec(db, "UPDATE test SET value = 'world' WHERE id = 1", NULL, NULL, NULL);sqlite3_close(db);return 0;
}

该示例实现了当UPDATE语句在表test中更新主键值为1的数据时,如果该行数据不存在,则新增一行数据,并将value列的值设置为"new value"。

注意:在调用sqlite3_preupdate_new()函数之后,必须通过sqlite3_preupdate_set()设置新插入行的数据,这样才能正常插入数据。

45.sqlite3_preupdate_old

sqlite3_preupdate_old函数用于获取UPDATE事件中的旧行数据。当执行UPDATE语句时,旧行数据需要在sqlite3_preupdate_hook回调函数中使用,例如用于记录更改日志或在更新前对比新旧数据等。

该函数的原型如下:

const void *sqlite3_preupdate_old(sqlite3 *db,int op,const char *zDb,const char *zName,sqlite_int64 iKey
);

该函数的参数说明如下:

- db: 数据库连接句柄。
- op: 操作类型,取值为SQLITE_INSERT或SQLITE_UPDATE。
- zDb和zName: 数据库名和表名。
- iKey: 主键值。

该函数必须在sqlite3_preupdate_hook回调函数中调用,并在调用sqlite3_preupdate_step()之前被调用。返回值是一个指向旧行数据的指针,如果该行不存在,则返回NULL。

下面是一个示例,该示例在UPDATE事件中获取旧行数据并输出:

#include <sqlite3.h>
#include <stdio.h>
static void preupdate_callback(sqlite3 *db,  // 数据库连接句柄void *pArg,   // 用户指针int iCmd,     // 修改命令类型char const *zDb,  // 数据库名char const *zName, // 表名sqlite3_int64 arg1,  // 行IDsqlite3_int64 arg2,  // 新行IDint arg3             // 列ID
) {if (iCmd == SQLITE_UPDATE) {const void *old_data = sqlite3_preupdate_old(db, SQLITE_UPDATE, zDb, zName, arg1);if (old_data) {printf("old data: id=%lld, value=%s\n", arg1, (const char*)sqlite3_value_text((sqlite3_value*)old_data + 1));} else {printf("old data not found: id=%lld\n", arg1);}}
}
int main() {sqlite3 *db;sqlite3_open(":memory:", &db);sqlite3_exec(db, "CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)", NULL, NULL, NULL);sqlite3_preupdate_hook(db, preupdate_callback, NULL);sqlite3_exec(db, "INSERT INTO test (id, value) VALUES (1, 'hello')", NULL, NULL, NULL);sqlite3_exec(db, "UPDATE test SET value = 'world' WHERE id = 1", NULL, NULL, NULL);sqlite3_exec(db, "DELETE FROM test WHERE id = 1", NULL, NULL, NULL);sqlite3_close(db);return 0;
}

该示例在UPDATE事件中获取id为1的旧行数据,并输出id和value的值。如果旧行数据不存在,则输出"old data not found"。需要注意的是,在sqlite3_value_text()函数中传入的参数是一个指向sqlite3_value结构体的指针。

46.sqlite3_progress_handler 

sqlite3_progress_handler函数用于安装一个进度回调函数,用于检查长时间运行的语句的运行时间,并防止其耗费太多的CPU。如果在指定的运行时间内没有回调函数,则sqlite3_progress_handler将返回非零值,从而终止长时间运行的语句。

函数原型:
void sqlite3_progress_handler(sqlite3 *db, int iInterval, int(*xCallback)(void*), void *pArg);
函数参数说明:

- db:需要监听的数据库。
- iInterval:回调函数被调用的时间间隔,以毫秒为单位。如果iInterval为0,则将调用回调函数,在执行每个数据库操作之前检查是否需要中止操作。如果iInterval不为0,则在执行每个数据库操作之前等待iInterval毫秒,并且在时间到期时调用回调函数以检查操作是否应继续。
- xCallback:回调函数指针,指向一个返回整数的函数。如果回调函数返回非零值,则长时间运行的语句将被终止。如果回调函数返回零值,则长时间运行的语句将继续运行。
- pArg:传递给回调函数的用户指针。

下面是一个简单的示例:

#include <sqlite3.h>
#include <stdio.h>
#include <unistd.h>

static int progress_callback(void *pArg) {
    printf("progress_callback\n");
    return 0;
}

int main() {
    sqlite3 *db;
    sqlite3_open(":memory:", &db);
    sqlite3_progress_handler(db, 1000, progress_callback, NULL);
    sqlite3_exec(db, "CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)", NULL, NULL, NULL);
    sqlite3_exec(db, "INSERT INTO test VALUES (1, 'hello')", NULL, NULL, NULL);
    sleep(2);
    sqlite3_finalize(db);
    return 0;
}
该示例在打开数据库连接后安装了一个回调函数,在操作一个语句时,程序会暂停2秒。在这个暂停的过程中,回调函数每隔1秒钟被调用一次,当到达1秒和2秒时,由于回调函数返回0,长时间运行的操作仍会继续运行。在操作完成之后,关闭数据库连接。

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

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

相关文章

Docker入门二(应用部署、迁移与备份、DockerFile、docker私有仓库、Docker-Compose)

文章目录 一、应用部署1.MySQL部署2.Redis部署3.Nginx部署 二、迁移与备份1.容器做成镜像2.镜像备份和恢复(打包成压缩包&#xff09; 三、DockerFile0.镜像从哪里来&#xff1f;1.什么是DockerFile2.DockerFile 构建特征3.DockerFile命令描述4.构建一个带vim的centos镜像案例5…

Redis中的HyperLogLog以及HyperLogLog原理

大家在学习redis的过程中&#xff0c;除了String&#xff0c;list&#xff0c;hash&#xff0c;set&#xff0c;zset这五种基本的数据结构&#xff0c;一定还会接触到几种高级的数据结构&#xff0c;比如bitmap&#xff0c;geo&#xff0c; 还有今天我们要说的hyperloglog&…

Rancher操作手册(v2.7.5-rc1)

1.登录 访问地址&#xff1a;10.66.55.132使用账号和密码登录。初始的页面是英文版本&#xff0c;可以点击左下方改为简体中文 登录成功后可以看到现有的集群。右上角可以进行新集群的创建和导入已有集群。点击箭头所指的蓝色集群名称可以进入集群。 2.集群仪表盘 进入到集…

微信小程序开发系列(三十四)·自定义组件的创建、注册以及使用(数据和方法事件的使用)

目录 1. 分类和简介 2. 公共组件 2.1 创建 2.2 注册 2.3 使用 3. 页面组件 3.1 创建 3.2 注册 3.3 使用 4. 组件的数据和方法的使用 4.1 组件数据的修改 4.2 方法事件的使用 1. 分类和简介 小程序目前已经支持组件化开发&#xff0c;可以将页面中的功能…

如何通过小程序上的产品力和品牌力提升用户的复购能力?

随着网络购物小程序的发展以及内容电商、社交电商、垂直电商、品牌自营等多个细分类型的出现&#xff0c;小程序成为用户日常购物、大促囤货以及首发抢购的重要场景&#xff0c;市场竞争也逐渐激烈。如何在用户侧获得更多转化、留存与复购&#xff0c;成为企业品牌日益关注的话…

全国农产品价格分析预测可视化系统设计与实现

全国农产品价格分析预测可视化系统设计与实现 【摘要】在当今信息化社会&#xff0c;数据的可视化已成为决策和分析的重要工具。尤其是在农业领域&#xff0c;了解和预测农产品价格趋势对于农民、政府和相关企业都至关重要。为了满足这一需求&#xff0c;设计并实现了全国农产…

npm包、全局数据共享、分包

使用 npm 包 小程序对 npm 的支持与限制 目前&#xff0c;小程序中已经支持使用 npm 安装第三方包&#xff0c;从而来提高小程序的开发效率。但是&#xff0c;在小程序中使用npm 包有如下 3 个限制&#xff1a; ① 不支持依赖于 Node.js 内置库的包 ② 不支持依赖于浏览器内置…

客户端:Vue3,服务端:Node,基于Socket.IO实现单聊的功能

目录 1.介绍 2.环境搭建 3.本功能实现的主要逻辑 4.客户端和服务端的主要代码 5.效果展示 6.socket.io的运作原理 1.介绍 本篇主要讲讲基于Socket.IO实现单聊功能的主要实现&#xff0c;包括了客户端和服务端Node。 在这个即时通讯无处不在的时代&#xff0c;实时聊天功能…

利用express从0到1搭建后端服务

目录 步骤一&#xff1a;安装开发工具步骤二&#xff1a;安装插件步骤三&#xff1a;安装nodejs步骤四&#xff1a;搭建启动入口文件步骤五&#xff1a;启动服务器总结 在日常工作中&#xff0c;有很多重复和繁琐的事务是可以利用软件进行提效的。但每个行业又有自己的特点&…

wsl ubuntu 安装cuda nvcc环境

wsl ubuntu 安装cuda环境&#xff1a; CUDA Toolkit 11.6 Downloads | NVIDIA DeveloperDownload CUDA Toolkit 11.6 for Linux and Windows operating systems.https://developer.nvidia.com/cuda-11-6-0-download-archive?target_osLinux&target_archx86_64&Distri…

前后端分离:现代Web开发的协作模式

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

金鸣表格文字识别大师:解决医学文档PDF生僻字识别难题的利器

在医学领域&#xff0c;文档资料常常涉及到大量的专业术语和生僻字&#xff0c;例如唑吡坦、哌替啶、氟桂利嗪等。这些专业词汇对于非专业人士来说可能较为陌生&#xff0c;但在医学研究和临床实践中却具有不可或缺的重要性。然而&#xff0c;当这些生僻字出现在PDF文档中&…