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://xiahunao.cn/news/2869984.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Camtasia 2023 中文MacOS

Camtasia 2023软件在录屏软件中的确表现突出&#xff0c;可以说是佼佼者之一。这款软件不仅功能强大&#xff0c;而且操作简便&#xff0c;适用于各种屏幕录制和视频编辑需求。 一、屏幕录制与视频导入 Camtasia 2023提供了高清的屏幕录制功能&#xff0c;可以轻松地捕捉电脑…

SpringCloud-深度理解ElasticSearch

一、Elasticsearch概述 1、Elasticsearch介绍 Elasticsearch&#xff08;简称ES&#xff09;是一个开源的分布式搜索和分析引擎&#xff0c;构建在Apache Lucene基础上。它提供了一个强大而灵活的工具&#xff0c;用于全文搜索、结构化搜索、分析以及数据可视化。ES最初设计用…

应用程序开发教学:医保购药系统源码搭建实战

医保购药系统作为医疗服务的重要组成部分&#xff0c;其开发不仅能够为患者提供更加便捷的购药服务&#xff0c;还能够提高医疗机构的管理效率。接下来&#xff0c;小编将为您讲解医保购药系统的源码搭建过程&#xff0c;介绍应用程序开发的基本步骤和技巧。 一、系统设计 我…

矩阵中移动的最大次数

文章目录 所属专栏:BFS算法 题目链接 思路如下&#xff1a; 1.首先我们需要从第一列开始遍历&#xff0c;寻找每一个都能够满足条件的位置&#xff0c;将它插入到数组里面 2.第一列遍历完了后我们先判断第一列的数是否都满足条件插入到数组里面&#xff0c;如果数组为空&#…

关于微信公众号的一些个心得(持续更新)

微信公众号也是写一些个人心得&#xff0c;也不指望有人关注什么的&#xff0c;如果在一个领域可以深耕的话也希望可以做一些分享。目前也就是写一些心得和体验&#xff0c;摘抄一类的。 字体大小和排版什么的有没有人有经验啊 安装编辑插件&#xff0c;以chorme浏览器为例&a…

ClickHouse:一款高效且强大的列式数据库管理系统

ClickHouse是一款开源的列式数据库管理系统&#xff0c;专为大规模数据仓库和数据分析应用而设计。它允许用户快速地存储和处理海量数据&#xff0c;同时提供了简单易用的SQL接口。本文将介绍ClickHouse的概念、技术原理以及使用案例&#xff0c;并探讨其优势和挑战。 一、引言…

从SLC 到 MLC、TLC颗粒

*以下是个人对相关基础知识的梳理和总结&#xff0c;对于高度专业性的知识个人理解可能会有出入&#xff0c;如果有误&#xff0c;希望各位大佬不吝指教&#xff1b; 1.SLC 颗粒 &#xff08;Single-Level Cell&#xff09; SLC颗粒每个储存单元只存储一个信息位&#xff08;即…

VMware Fusion 13.5.1 OEM BIOS Version - 在 macOS 中运行 Windows 虚拟机的最佳方式

VMware Fusion 13.5.1 OEM BIOS Version VMware Fusion 13 原版 App 中集成 OEM BIOS 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-fusion-13-oem/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 使用 VMware …

世界环境绩效指数EPI数据集(2000-2022年)

环境绩效指数&#xff08;EPI&#xff09;是由耶鲁大学和哥伦比亚大学联合发布的一项综合指标&#xff0c;旨在衡量世界各国在可持续环境管理方面的表现。覆盖2000年至2022年&#xff0c;EPI通过分析各国在多个维度上的环境政策执行成效&#xff0c;包括空气质量、水资源管理、…

RequestResponse使用

文章目录 一、Request&Response介绍二、Request 继承体系三、Request 获取请求数据1、获取请求数据方法&#xff08;1&#xff09;、请求行&#xff08;2&#xff09;、请求头&#xff08;3&#xff09;、请求体 2、通过方式获取请求参数3、IDEA模板创建Servlet4、请求参数…

第二百零六回

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"给geolocator插件提交问题的结果"相关的内容&#xff0c;本章回中将介绍自定义标题栏.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我…

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

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

台球厅麻将 馆用什么收银系统,如何下载可接灯控桌球棋牌计时计费管理系统软件

台球厅麻将 馆用什么收银系统&#xff0c;如何下载可接灯控桌球棋牌计时计费管理系统软件 一、前言 以下软件操作教程以 佳易王台球计时计费管理系统软件V18.0为例说明 件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、软件可以同时适用于台球和棋牌&am…

Parade Series - Web Streamer Low Latency

Parade Series - FFMPEG (Stable X64) 延时测试秒表计时器 ini/config.ini [system] homeserver storestore\nvr.db versionV20240312001 verbosefalse [monitor] listrtsp00,rtsp01,rtsp02 timeout30000 [rtsp00] typelocal deviceSurface Camera Front schemartsp ip127…

2024最新PHP彩虹网盘与外链分享程序,支持所有格式文件的上传

彩虹外链网盘是一款基于PHP的在线存储和分享平台&#xff0c;它允许用户上传各种类型的文件&#xff0c;并提供了生成文件链接、图片链接、音乐和视频链接的功能。同时&#xff0c;它还会自动生成相应的UBB代码和HTML代码&#xff0c;支持文本、图片、音乐和视频的在线预览。这…

jvm 内存泄露、内存溢出、栈溢出区别

JVM&#xff08;Java虚拟机&#xff09;是负责执行Java程序的运行环境。以下是对内存泄露、内存溢出和栈溢出这几个概念的解释&#xff1a; 内存泄露&#xff08;Memory Leak&#xff09;&#xff1a; 内存泄露指的是程序中分配的内存空间在不再被使用时没有被释放的情况。这可…

【热门话题】前端框架发展史

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 前端开发的历史演变引言第一章&#xff1a;起源与基础建设 - HTML与CSS时代1.1 …

ubuntu安装docker的详细教程

检查卸载老版本docker ubuntu下自带了docker的库&#xff0c;不需要添加新的源。 但是ubuntu自带的docker版本太低&#xff0c;需要先卸载旧的再安装新的。 注&#xff1a;docker的旧版本不一定被称为docker&#xff0c;docker.io 或 docker-engine也有可能&#xff0c;所以卸…

深度学习——SAM(Segment-Anything)代码详解

目录 引言代码目录segment-anything 代码详解build_sam.pypredictor.pyautomatic_mask_generator.py 引言 从去年年初至今&#xff0c;SAM(Segment Anything )已经问世快一年了&#xff0c;SAM凭借其强大而突出的泛化性能在各项任务上取得了优异的表现&#xff0c;广大的研究者…

简单的arduino实验理解串口通信(uart为例)独立硬件的信息交互

前言 接触过单片机的人都知道串口通信&#xff0c;可以通过另一个短文了解,其中入门的应该就是串口通信了。UART全拼的个人理解为通用的异步接收和发送。常见两根短线作为通信线&#xff0c;一般使用TXD和RXD标记。对于两块通信的芯片来说&#xff0c;接收和发送是相对的&…