Sqlite3数据库表内数据批量读取操作---sqlite3_stmt机制

2024-08-23 22:12

本文主要是介绍Sqlite3数据库表内数据批量读取操作---sqlite3_stmt机制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

0、引言

        在前面两篇文章已经对数据环境搭建、数据批量写入库中进行了较为详细的讲解。因此,基于前两篇文章内容的基础上,本文主要从数据库中批量数据读取操作进行梳理讲解。

        嵌入式数据库SQLite 3配置使用详细笔记教程_sqlite3-CSDN博客

        SQLite 3 优化批量数据存储操作---事务transaction机制_sqlite3 事务-CSDN博客

        数据库,顾名思义,是一个数据存储的容器、装置,既能存储用户的数据,也能将存储的数据读取出来处理。但是,要怎么做才能把数据读取出来又能保证效率呢?基于这个问题,本文将对sqlite3_stmt机制进行说明,并实现数据的读取。

1、sqlite3_stmt机制

        sqlite3_stmt 是 SQLite 数据库在 C 语言接口中使用的一个关键数据结构,它代表了一个“准备语句对象”(prepared statement object),也是一个预编译的 SQL 语句,预编译 SQL 语句可以提高执行效率并防止 SQL 注入攻击。这个对象是对 SQL 语句的一种封装,该 SQL 语句已经被编译成字节码形式,可以直接由 SQLite 的虚拟机执行。

        在 SQLite 中,预编译 SQL 语句有如下的几个优点

①、性能提升:预编译的语句可以被数据库引擎更快地执行,因为编译步骤已经在准备阶段完成了。

②、安全性:使用预编译语句可以有效防止 SQL 注入攻击,因为参数值在执行时是分开绑定的,不会与 SQL 代码混合。

③、减少内存占用:对于重复执行的 SQL 语句,预编译可以减少内存的使用,因为相同的 SQL 代码只需要编译一次。

        使用sqlite3_stmt基本步骤如下:

(1)、打开 SQLite 数据库连接(使用 sqlite3_open() 函数)。

(2)、准备 SQL 语句(使用 sqlite3_prepare_v2() 或 sqlite3_prepare16_v2() 函数)。

(3)、绑定参数(如果有的话,使用 sqlite3_bind_*() 系列函数)。

(4)、执行 SQL 语句(使用 sqlite3_step() 函数)。

(5)、处理结果集(如果有的话,使用 sqlite3_column_*() 系列函数)。

(6)、重置或清理 SQL 语句(使用 sqlite3_reset() 或 sqlite3_finalize() 函数)。

(7)、关闭数据库连接(使用 sqlite3_close() 函数)。

        如果只是读取一条数据时,使用sqlite3_exec和sqlite3_stmt效率是一样的,但是当涉及到大批量的操作时,此前使用的sqlite3_exec就会不是最优选择了,因此推荐使用sqlite3_stmt机制。

2、常用API说明

        从上图所示的Sqlite3的官方网站查询的数据信息可以看到,sqlite3_stmt相关的API有50多个。因此本文这一部分将对sqlite3_stmt常用的API进行介绍。

①、sqlite3_prepare_v2

int sqlite3_prepare_v2(sqlite3 *db,            /* 数据库连接 */const char *zSql,       /* SQL 文本 */int nByte,              /* SQL 文本的最大长度,-1 表示自动计算长度 */sqlite3_stmt **ppStmt,  /* 输出参数,指向预编译语句对象的指针 */const char **pzTail      /* 输出参数,指向 SQL 文本中未处理部分的指针 */
);//成功返回SQLITE_OK (0),失败返回错误码

        sqlite3_prepare_v2() 函数的主要用途是将 SQL 文本编译成一个可以执行的预编译语句对象。预编译语句在执行前可以进行参数绑定,这样可以提高执行效率并防止 SQL 注入攻击。这个函数是 sqlite3_prepare() 的改进版本,提供了更多的功能和更好的错误报告。

②、sqlite3_step

int sqlite3_step(sqlite3_stmt *pStmt);
//pStmt:一个指向预编译语句对象(sqlite3_stmt)的指针。//返回值:
//SQLITE_ROW(1):如果执行成功并且结果集中还有更多的行。
//SQLITE_DONE(100):如果执行成功并且所有行都已经被处理完毕。
//如果发生错误,返回错误码

        sqlite3_step用于执行一个预编译的 SQL 语句,这个函数会执行语句,并将结果集推进到下一行(如果有的话)。当所有行都被处理完毕时,sqlite3_step() 返回 SQLITE_DONE。

③、sqlite3_bind_text

int sqlite3_bind_text(
sqlite3_stmt *stmt,  /*stmt:一个指向预编译语句对象(sqlite3_stmt)的指针。*/
int idx,             /*idx:占位符的索引,从 1 开始计数。*/
const char *zData,   /*zData:要绑定的文本数据的指针。*/
int nData,           /*nData:文本数据的长度(以字节为单位)。如果设置为 -1,SQLite 会自动计算文本的长度。*/
void (*xDel)(void *) /*一个可选的删除函数,用于在 sqlite3_finalize() 调用时释放 zData 指向的内存。如不需要释放内存,可以传递SQLITE_STATIC 或 NULL。*/
);//成功返回SQLITE_OK (0),失败返回错误码

        sqlite3_bind_text用于将文本类型的参数绑定到一个预编译的 SQL 语句(sqlite3_stmt)中的占位符。这个函数允许安全地将变量值插入到 SQL 语句中,从而避免 SQL 注入攻击。

④、sqlite3_column_int64

int64_t sqlite3_column_int64(sqlite3_stmt *stmt, int iCol);
//stmt:一个指向预编译语句对象(sqlite3_stmt)的指针。
//iCol:要获取的列的索引,从 0 开始计数。//成功返回指定列的 int64_t 类型的值,失败返回0

        sqlite3_column_int64用于从结果集中获取一个 int64_t 类型的列值。这个函数通常与 sqlite3_step() 函数一起使用,用于遍历查询结果。

⑤、sqlite3_column_text

const unsigned char *sqlite3_column_text(sqlite3_stmt *stmt, int iCol);
//stmt:一个指向预编译语句对象(sqlite3_stmt)的指针。
//iCol:要获取的列的索引,从 0 开始计数。//成功,返回指向指定列文本值的指针,失败返回NULL

        sqlite3_column_text用于从结果集中获取一个文本类型的列值。这个函数通常与 sqlite3_step() 函数一起使用,用于遍历查询结果。

        提醒:返回的指针指向的是 SQLite 内部的数据结构,不能直接修改或释放这部分内存当 sqlite3_stmt 对象被销毁(例如通过调用 sqlite3_finalize())时,这部分内存也会被自动释放

⑥、sqlite3_column_double

double sqlite3_column_double(sqlite3_stmt *stmt, int iCol);
//stmt:一个指向预编译语句对象(sqlite3_stmt)的指针。
//iCol:要获取的列的索引,从 0 开始计数。//成功,返回返回指定列的 double 类型的值,失败返回0.0

        sqlite3_column_double用于从结果集中获取一个double类型的列值。这个函数通常与 sqlite3_step() 函数一起使用,用于遍历查询结果。

⑦、sqlite3_finalize

int sqlite3_finalize(sqlite3_stmt *stmt);
//stmt:一个指向预编译语句对象(sqlite3_stmt)的指针。//成功返回SQLITE_OK (0),失败返回错误码

        用于清理和释放一个预编译的 SQL 语句对象(sqlite3_stmt)。

3、程序示例

        在编写此参考程序示例时,使用的是之前存储下来的一个数据库中的一个表,该表的格式如下:

        根据上图所示的内容,可以看到,该表中一共有6个数据,3种数据类型,分别是integer、text和real类型。接下来将对表中的数据进行读取解析并可视化呈现出来。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sqlite3.h>typedef struct {long long store_time;char name[20];double detect_time;float x;float y;float z;
}user_data_t;/*** @brief  读取Sqlite数据库中的xxx数据* @param  db:数据库文件描述符* @param  data:存储读取出来的数据* @retval 成功返回实际读取的数据个数,失败返回-1*/
int sqlite3_read_xxx_data(sqlite3* db, user_data_t* data, int max_count)
{if (db == NULL) {DBUG_SHOW(DBUG_ERROR, "%s Variable db is NULL!\n", __FUNCTION__);return -1;}char sql_cmd[] = "SELECT * FROM detect;";int ret = 0;sqlite3_stmt* stmt = NULL;const char* err_msg = NULL;ret = sqlite3_prepare_v2(db, sql_cmd, -1, &stmt, NULL);if (ret != SQLITE_OK) {DBUG_SHOW(DBUG_ERROR, "Prepare statement err: %s\n", sqlite3_errmsg(db));return -1;}int count = 0;while ((ret = sqlite3_step(stmt)) == SQLITE_ROW && count < max_count) {data[count].store_time = sqlite3_column_int64(stmt, 0);strncpy(data[count].name, (const char*)sqlite3_column_text(stmt, 1), sizeof(data[count].name) - 1);data[count].name[sizeof(data[count].name) - 1] = '\0';data[count].detect_time = sqlite3_column_double(stmt, 2);data[count].x = sqlite3_column_double(stmt, 3);data[count].y = sqlite3_column_double(stmt, 4);data[count].z = sqlite3_column_double(stmt, 5);count++;}if (ret != SQLITE_DONE) {err_msg = sqlite3_errmsg(db);if (strcmp(err_msg, "another row available") == 0) {DBUG_SHOW(DBUG_WARN, "This table has another row data available!\n");}else {DBUG_SHOW(DBUG_ERROR, "Fetch data err: %s\n", err_msg);sqlite3_finalize(stmt);return -1;}}sqlite3_finalize(stmt);return count;
}int main(void)
{sqlite3* read_db = NULL;char filename[256] = "2024081214134452.db";database_init(&read_db, filename);detect_database_t* data = malloc(sizeof(detect_database_t) * 512);int ret = sqlite3_read_xxx_data(read_db, data, 512);printf("data num : %d\n", ret);for (int i = 0; i < ret; i++) {printf(".......................................\n");printf("store_time:%lld\n", data[i].store_time);printf("name:%s\n", data[i].name);printf("detect_time:%.3f\n", data[i].detect_time);printf("x:%.3f\n", data[i].x);printf("y:%.3f\n", data[i].y);printf("z:%.3f\n", data[i].z);}free(data);while (1);
}

4、程序效果

        在读取数据库前,通过SQLite Studio程序查看了数据库中,共存放了211条有效数据。

        运行程序后,从可以看到,读取出了211条数据,且经过对比核验,读出的数据与库中的数据保持一致。

这篇关于Sqlite3数据库表内数据批量读取操作---sqlite3_stmt机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

SQL server数据库如何下载和安装

《SQLserver数据库如何下载和安装》本文指导如何下载安装SQLServer2022评估版及SSMS工具,涵盖安装配置、连接字符串设置、C#连接数据库方法和安全注意事项,如混合验证、参数化查... 目录第一步:打开官网下载对应文件第二步:程序安装配置第三部:安装工具SQL Server Manageme

C#连接SQL server数据库命令的基本步骤

《C#连接SQLserver数据库命令的基本步骤》文章讲解了连接SQLServer数据库的步骤,包括引入命名空间、构建连接字符串、使用SqlConnection和SqlCommand执行SQL操作,... 目录建议配合使用:如何下载和安装SQL server数据库-CSDN博客1. 引入必要的命名空间2.

Java中读取YAML文件配置信息常见问题及解决方法

《Java中读取YAML文件配置信息常见问题及解决方法》:本文主要介绍Java中读取YAML文件配置信息常见问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要... 目录1 使用Spring Boot的@ConfigurationProperties2. 使用@Valu

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式

《Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式》本文详细介绍如何使用Java通过JDBC连接MySQL数据库,包括下载驱动、配置Eclipse环境、检测数据库连接等关键步骤,... 目录一、下载驱动包二、放jar包三、检测数据库连接JavaJava 如何使用 JDBC 连接 mys

SQL中如何添加数据(常见方法及示例)

《SQL中如何添加数据(常见方法及示例)》SQL全称为StructuredQueryLanguage,是一种用于管理关系数据库的标准编程语言,下面给大家介绍SQL中如何添加数据,感兴趣的朋友一起看看吧... 目录在mysql中,有多种方法可以添加数据。以下是一些常见的方法及其示例。1. 使用INSERT I

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

Java操作Word文档的全面指南

《Java操作Word文档的全面指南》在Java开发中,操作Word文档是常见的业务需求,广泛应用于合同生成、报表输出、通知发布、法律文书生成、病历模板填写等场景,本文将全面介绍Java操作Word文... 目录简介段落页头与页脚页码表格图片批注文本框目录图表简介Word编程最重要的类是org.apach

MySQL 删除数据详解(最新整理)

《MySQL删除数据详解(最新整理)》:本文主要介绍MySQL删除数据的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、前言二、mysql 中的三种删除方式1.DELETE语句✅ 基本语法: 示例:2.TRUNCATE语句✅ 基本语

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2