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

2024-03-14 06:36

本文主要是介绍SQLiteC/C++接口详细介绍之sqlite3类(五),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

   快速跳转文章列表:SQLite—系列文章目录

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

 下一篇:SQLiteC/C++接口详细介绍之sqlite3类(六)(未发表)

14.sqlite3_busy_handler函数:

用于在访问共享数据库时处理数据库锁定,并如果某个共享数据库已经处于锁定状态,则可以排队查询等待一段时间,或在达到最大等待时限时放弃等待查询,从而避免资源浪费和死锁问题。

函数的原型:

int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);

其中第一个参数是要操作的数据库句柄,第二个参数是一个函数指针,用于在数据库被锁时进行回调,第三个参数是传递给回调函数的上下文参数。
回调函数需要返回一个值,以确定是否继续等待或放弃查询等待,如果返回0,则一直等待,如果返回非零值,则直接中断查询。
注意:sqlite3_busy_handler函数不能在事务过程中使用,否则会影响数据库会话的一致性和完整性。因此,在使用此函数之前,应先检查当前是否存在任何激活的事务,并在必要时回滚事务,以免引起意外的数据库文件损坏。

例如:

1. 定义回调函数:为了使用sqlite3_busy_handler(),需要先定义一个回调函数。该函数有两个参数,即被占用的数据库对象和被占用次数。如果该函数返回0,则表示可以继续尝试访问该对象;如果返回非0值,则表示等待指定时间后再次尝试访问。

   static int callback(void *data, int count) {int delay = 1000;printf("Database is busy, waiting %d ms...\n", delay);usleep(delay * 1000);return 1;}

   在上面的代码中,我们定义了一个名为callback()的回调函数,当访问数据库时发生"Busy"错误时,该函数将等待1秒后再次尝试访问。如果该回调函数返回1,则下次访问将再次询问该回调函数。
2. 注册回调函数:在使用sqlite3_open()打开数据库时,可以使用sqlite3_busy_handler()函数注册上面定义的回调函数。

   sqlite3 *db;int rc = sqlite3_open("mydb.db", &db);if (rc == SQLITE_OK) {sqlite3_busy_handler(db, callback, NULL);// ...}   

   在上面的代码中,我们在打开名为mydb.db的数据库时,使用了sqlite3_busy_handler()函数注册了callback()回调函数。
在使用sqlite3_busy_handler()处理"Busy"错误时,需要注意一些问题:
- 该函数注册的回调函数只有在执行一些特定的SQL语句时才会被调用,例如UPDATE、INSERT、DELETE等更新操作。
- 回调函数需要注意自旋锁问题(spin-lock),以防止死循环和线程或进程卡死。
- 注册回调函数可能会影响数据库的性能,因此需要根据具体情况进行测试和调整。
在多个线程或者进程并发访问SQLite数据库时,使用sqlite3_busy_handler()函数可以有效地避免"Busy"错误,并提高程序的可靠性和稳定性。

15.sqlite3_db_name函数

在多数据库连接的情况下用于获取给定数据库连接或游标所关联的数据库的名称。这个函数可以用于跟踪数据库文件的来源及管理,特别是在使用动态绑定的SQL语句时。 

函数的原型:

const char *sqlite3_db_name(sqlite3 *db, const char *zDbName);
const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);

其中db参数是一个指向SQLite数据库连接对象的指针,zDbName参数是一个指向包含所需数据库名称的字符数组的指针。如果第二个参数不为NULL,则该函数将获取指定列,否则默认获取主数据库连接或游标所关联的数据库名称。
函数返回值是一个指向包含数据库名称的空终止字符串的指针。如果指定的数据库不存在,则返回NULL。
注意:sqlite3_db_name函数只能在一个已打开的数据库连接上使用,并且仅能返回当前打开的数据库的名称,不能获取SQLite中所有数据库的名称。如果需要获取所有数据库的名称,则需要执行SQLite系统表查询或系统函数调用。 

例如:

下面是sqlite3_db_name()的使用方法:
 获取数据库名称:使用sqlite3_db_name()函数获取该连接对象关联的数据库名称。  

 const char *db_name = sqlite3_db_name(db, 0);printf("Database name: %s\n", db_name);

  在上面的代码中,我们使用sqlite3_db_name()函数获取与db连接相关联的数据库的名称,并将其打印出来。
注意:如果一个数据库连接关联多个数据库,比如通过ATTACH命令关联多个数据库时,sqlite3_db_name()函数将返回最近一次执行的SQL语句中指定的数据库名称。如果没有指定数据库名称,则返回NULL。 

16.sqlite3_busy_timeout函数

设置在多用户或多线程并发访问文件时等待其它连接锁释放的最大时间。当某个连接在对资源进行访问时,如果资源已被另一个连接锁定,则该连接将等待指定的时间,直到资源被释放或达到指定的最大等待时间为止。

函数的原型:

int sqlite3_busy_timeout(sqlite3*, int ms);

 其中ms参数表示等待的毫秒数,如果为非正数,则取消忙等待并释放连接锁。函数的返回值表示是否设置成功,如果返回SQLITE_OK,则表示设置成功,否则返回相应的错误码。
注意:sqlite3_busy_timeout函数必须在连接之前进行调用,否则设置将不起作用。此外,在使用此函数时应注意避免死锁问题,例如设置一个合适的等待时间,并在必要时使用函数进行回调,以避免长时间等待导致资源浪费和死锁问题。

1. 设置"busy"超时:使用sqlite3_busy_timeout()函数设置在访问数据库时发生"Busy"错误时等待的时间,单位为毫秒。
 

  sqlite3_busy_timeout(db, 5000);

  在上面的代码中,我们设置等待时间为5000毫秒,即5秒。
2. 访问数据库:在设置"busy"超时后,可以开始访问数据库。

   int result = sqlite3_exec(db, "SELECT * FROM mytable", callback, 0, &zErrMsg);if (result != SQLITE_OK) {fprintf(stderr, "SQL error: %s\n", zErrMsg);sqlite3_free(zErrMsg);}

在上面的代码中,db是我们打开数据的对象我们使用sqlite3_exec()函数执行SQL语句并处理结果。
注意:
sqlite3_busy_timeout()只对在访问数据库时发生的"Busy"错误起作用。如果程序占用数据库长时间不释放,造成阻塞,这时sqlite3_busy_timeout()就不起作用了。在实际使用中,应该在编写程序时避免出现长时间占用数据库的情况。

17.sqlite3_db_readonly函数用于判断指定的数据库连接或游标是否处于只读模式。 

函数的原型:

int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);

其中,参数db是一个指向SQLite数据库连接对象的指针,参数zDbName是一个指向包含所需数据库名称的字符数组的指针。如果第二个参数不为NULL,则该函数将获取指定列,否则默认获取主数据库连接或游标所关联的数据库。
函数返回值是一个整数,表示指定数据库是否处于只读模式。返回值为1时表示该数据库处于只读模式,返回值为0表示该数据库可以进行读写操作。
注意:此函数只能用于已经打开的数据库连接或游标。  

例如: 

判断数据库是否为只读:使用sqlite3_db_readonly()函数判断数据库是否为只读。

int is_readonly = sqlite3_db_readonly(db, "main");
if (is_readonly == 1) {printf("The database is readonly\n");} else {printf("The database is not readonly\n");}

代码中,db是数据库连接对象,使用sqlite3_db_readonly()函数判断与db对象相关联的名为main的数据库是否为只读。如果该数据库只读,则打印"The database is readonly",否则打印"The database is not readonly"。
注意:sqlite3_db_readonly()函数的第二个参数指定要查询的数据库名称。如果没有指定任何数据库名称,则默认查询"main"数据库。如果指定的数据库不存在,则返回-1。 

18.sqlite3_last_insert_rowid

函数用于获取最近插入数据的行ID 。

函数的原型:

sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);

函数返回一个sqlite_int64类型的值,表示最近一次插入数据的行ID。如果还未插入数据,则返回0。

例如:

在SQLite中,当表定义了一个自增长的主键字段时,插入一条新记录时,该字段将自动生成一个独一无二的值,我们可以使用sqlite3_last_insert_rowid()函数获取该值。
下面是sqlite3_last_insert_rowid()的使用方法:
1. 执行插入操作:使用SQL语句执行一条INSERT操作,在执行插入操作时,必须包含自增长的主键列。  

 sqlite3 *db;int rc = sqlite3_open("mydb.db", &db);if (rc == SQLITE_OK) {char *sql = "INSERT INTO mytable (name, age) VALUES ('Tom', 25)";rc = sqlite3_exec(db, sql, NULL, NULL, NULL);if (rc != SQLITE_OK) {printf("Error: %s\n", sqlite3_errmsg(db));}      }  

在上面的代码中,我们使用sqlite3_exec()函数执行一条INSERT语句,插入一条记录到名为mytable的表中。
2. 获取主键值:使用sqlite3_last_insert_rowid()函数获取自动生成的主键值。  

sqlite3_int64 last_rowid = sqlite3_last_insert_rowid(db);
printf("Last insert rowid: %lld\n", last_rowid);

  代码中,我们使用sqlite3_last_insert_rowid()函数获取刚插入记录的主键值,并将其打印出来。

注意:该函数只能用于最近执行的INSERT或REPLACE命令之后,否则将返回不可预测的结果。该函数不需要连接句柄或游标对象进行调用,只需要在执行INSERT或REPLACE命令之后立即调用即可。sqlite3_last_insert_rowid()函数获取自动生成的主键值只针对自增长的主键列有效,并且只能获取最近插入的记录的主键值。如果不存在自增长的主键列或者没有执行任何插入操作,则该函数返回0。

这篇关于SQLiteC/C++接口详细介绍之sqlite3类(五)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/807523

相关文章

Python pandas库自学超详细教程

《Pythonpandas库自学超详细教程》文章介绍了Pandas库的基本功能、安装方法及核心操作,涵盖数据导入(CSV/Excel等)、数据结构(Series、DataFrame)、数据清洗、转换... 目录一、什么是Pandas库(1)、Pandas 应用(2)、Pandas 功能(3)、数据结构二、安

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

Apache Ignite 与 Spring Boot 集成详细指南

《ApacheIgnite与SpringBoot集成详细指南》ApacheIgnite官方指南详解如何通过SpringBootStarter扩展实现自动配置,支持厚/轻客户端模式,简化Ign... 目录 一、背景:为什么需要这个集成? 二、两种集成方式(对应两种客户端模型) 三、方式一:自动配置 Thick

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

Python对接支付宝支付之使用AliPay实现的详细操作指南

《Python对接支付宝支付之使用AliPay实现的详细操作指南》支付宝没有提供PythonSDK,但是强大的github就有提供python-alipay-sdk,封装里很多复杂操作,使用这个我们就... 目录一、引言二、准备工作2.1 支付宝开放平台入驻与应用创建2.2 密钥生成与配置2.3 安装ali

2025版mysql8.0.41 winx64 手动安装详细教程

《2025版mysql8.0.41winx64手动安装详细教程》本文指导Windows系统下MySQL安装配置,包含解压、设置环境变量、my.ini配置、初始化密码获取、服务安装与手动启动等步骤,... 目录一、下载安装包二、配置环境变量三、安装配置四、启动 mysql 服务,修改密码一、下载安装包安装地

在macOS上安装jenv管理JDK版本的详细步骤

《在macOS上安装jenv管理JDK版本的详细步骤》jEnv是一个命令行工具,正如它的官网所宣称的那样,它是来让你忘记怎么配置JAVA_HOME环境变量的神队友,:本文主要介绍在macOS上安装... 目录前言安装 jenv添加 JDK 版本到 jenv切换 JDK 版本总结前言China编程在开发 Java

Spring Boot Actuator应用监控与管理的详细步骤

《SpringBootActuator应用监控与管理的详细步骤》SpringBootActuator是SpringBoot的监控工具,提供健康检查、性能指标、日志管理等核心功能,支持自定义和扩展端... 目录一、 Spring Boot Actuator 概述二、 集成 Spring Boot Actuat

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么