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.mzph.cn/news/750503.shtml

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

相关文章

PHP获取并分析过期删除.cn域名3-5数字(无4非0开)/2-4字母(声母)/三杂等品类域名

用途:获取分析最近过期删除.cn域名中3-5数字(无4非0开)/2-4字母(声母)/三杂等品类域名 先创建rec文件夹,用于按天缓存域名列表(不自动创建哦) 推荐宝塔灯自带的定时任务访问本文件网址&#xff0c;每早5-6点执行 获取两天后删除的cn域名名单并提取几个有价值类目的域名 <…

什么可以让你快速穿越低谷?

1. 变环境 当我们对当前生活状态感到彻底失望&#xff0c;当我们看透了人世间的冷暖&#xff0c;见证了人性的撕裂与拉扯&#xff0c;就会意识到需要改变环境。这可能包括搬离现居之地&#xff0c;寻找新的斗争之地。就像寻找宝玉发光之地一样&#xff0c;我们需要找到能让自己…

基于springboot的高校化学试剂仓储管理系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

VMware NSX Advanced Load Balancer (NSX ALB) 22.1.6 - 多云负载均衡平台

VMware NSX Advanced Load Balancer (NSX ALB) 22.1.6 - 多云负载均衡平台 应用交付&#xff1a;多云负载均衡、Web 应用防火墙和容器 Ingress 服务 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-nsx-alb-22/&#xff0c;查看最新版。原创作品&#xff0c;转载请…

194 基于matlab的日历GUI制作

基于matlab的日历GUI制作&#xff0c;可实时显示当前的日期和时间&#xff0c;精确到秒。非常漂亮&#xff0c;也很基础&#xff0c;学习GUI的不错程序&#xff0c;程序已调通&#xff0c;可直接运行。 194 matlab 日历制作 GUI可视化 - 小红书 (xiaohongshu.com)

sqlplus设置提示符

作为DBA&#xff0c;需要管理好多数据库&#xff0c;经常会有一台服务器安装多个oracle实例的情况&#xff0c;为避免误操作实例&#xff0c;我们需要在执行sqkplus前&#xff0c;先通过$ echo $ORACLE_SID或 SQL>select name from v$database查看当前实例&#xff0c;这样难…

前端小白的学习之路(CSS3 一)

提示&#xff1a;CSS3 是 Cascading Style Sheets&#xff08;层叠样式表&#xff09;的第三个主要版本&#xff0c;引入了许多新的特性和增强功能&#xff0c;用于设计和布局网页。本章记录CSS3新增选择器&#xff0c;盒子模型。 目录 一、C3新增选择器 1) 属性选择器 1.[c…

Python语言基础与应用-北京大学-陈斌-P40-39-基本扩展模块/上机练习:计时和文件处理-给算法计时-上机代码

Python语言基础与应用-北京大学-陈斌-P40-39-基本扩展模块/上机练习&#xff1a;计时和文件处理-给算法计时-上机代码 上机代码&#xff1a; # 基本扩展模块训练 给算法计时 def factorial(number): # 自定义一个计算阶乘的函数i 1result 1 # 变量 result 用来存储每个数的阶…

小结:Node.js Express VS Koa

Express 是一个基于 Node.js 平台的极简、灵活的 web 应用开发框架&#xff0c;主要基于 Connect 中间件&#xff0c;并且自身封装了路由、视图处理等功能&#xff0c;使用人数众多。 Koa 是 Express 原班人马基于 ES6 新特性重新开发的框架&#xff0c;主要基于 co 中间件&am…

RTP 控制协议 (RTCP) 反馈用于拥塞控制

摘要 有效的 RTP 拥塞控制算法&#xff0c;需要比标准 RTP 控制协议(RTCP)发送方报告(SR)和接收方报告(RR)数据包提供的关于数据包丢失、定时和显式拥塞通知 (ECN) 标记的更细粒度的反馈。 本文档描述了 RTCP 反馈消息&#xff0c;旨在使用 RTP 对交互式实时流量启用拥塞控制…

MongoDB数据备份与迁移

MongoDB数据备份与迁移 参考链接&#xff1a; https://www.cnblogs.com/you-men/p/14675290.html#_label2https://docs.mongoing.com/guan-li/mongodb-backup-methods#shi-yong-mongodump-bei-fenhttps://www.cnblogs.com/dbabd/p/13259147.html MongoDB备份工具简介 mongo…

Rust 的 Arc<Mutex<T>> 的用法示例源代码

在 Rust 中&#xff0c;Arc<Mutex<T>> 是一种组合类型&#xff0c;它结合了 Arc&#xff08;原子引用计数&#xff09;和 Mutex&#xff08;互斥锁&#xff09;。Arc 用于在多个所有者之间共享数据&#xff0c;而 Mutex 用于确保在任意时刻只有一个线程可以访问被保…

js使用canvas实现图片鼠标滚轮放大缩小拖拽预览,显示像素坐标,显示像素值

html代码 todo 实现画矩形框&#xff0c;圆形roi <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title&…

单元测试开发必不可少的一项工作,C#怎么来写单元测试

单元测试在开发过程中非常重要&#xff0c;写单元测试有几个重要的理由&#xff1a; 确保代码质量和稳定性&#xff1a; 单元测试可以帮助你验证代码的正确性。通过编写测试用例&#xff0c;你可以确保代码按照预期的方式工作&#xff0c;并且在进行重构或修改时不会破坏原有的…

JMeter 面试题及答案整理,最新面试题

JMeter中如何进行性能测试的规划和设计&#xff1f; 进行JMeter性能测试的规划和设计主要遵循以下几个步骤&#xff1a; 1、确定测试目标&#xff1a; 明确性能测试的目的和目标&#xff0c;比如确定要测试的系统性能指标&#xff08;如响应时间、吞吐量、并发用户数等&#…

zookeeper快速入门一:zookeeper安装与启动

本文是zookeeper系列之快速入门中的第一篇&#xff0c;欢迎大家观看与指出不足。 写在前面&#xff1a; 不影响教程&#xff0c;笔者安装zookeeper用的是WSL(windows下的linux子系统&#xff09;&#xff0c;当然你想直接在windows上用zookeeper也是可以的。 如果你也想用ws…

怎么判断发票扫描OCR软件好用不好用?

发票扫描OCR&#xff08;Optical Character Recognition&#xff09;是一种将纸质发票上的文字、数字等信息转化为可编辑的文本格式的技术。在现代企业中&#xff0c;随着数字化转型的推进&#xff0c;发票扫描OCR技术变得越来越重要。然而&#xff0c;面对市场上众多的发票扫描…

spring boot集成redis实现共享存储session

spring boot集成redis实现共享存储session redis实现共享存储session 首先下载redis,我下载的版本是5.0.14,目前官网貌似找不到5.x版本&#xff0c;可以自行去网上寻找。我这里的springboot版本是2.6.4引入redis依赖 <!-- https://mvnrepository.com/artifact/org.spring…

重拾C++之菜鸟刷算法第13篇---回溯算法

子集 知识点 子集问题中&#xff0c;不能包含重复子集&#xff0c;那么就需要startIndex来防止重复取值 题目 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任…

Android 设计模式观察者

Java观察者模式实现观察者模式的接口Observer和目标接口Subject,并实现了一个具体的目标类WeatherData。 同时,还实现了一个观察者类CurrentConditionsDisplay,它在目标类注册后,会在测量变化时接收到更新,并打印当前状况。最后在main函数中,我们创建了目标类的实例,并设…