嵌入式数据库sqlite3【进阶篇】-如何用C语言操作sqlite3,一文搞懂

2023-11-19

sqlite3编程接口非常多,对于初学者来说,我们暂时只需要掌握常用的几个函数,其他函数自然就知道如何使用了。

数据库

本篇假设数据库为my.db,有数据表student。

no name score
4 一口Linux 89.0

创建表格语句如下:

CREATE TABLE  IF NOT EXISTS student (no integer primary key, name text, score real);

常用函数

sqlite3_open

int   sqlite3_open(char  *path,   sqlite3 **db);
功能:
    打开sqlite数据库
参数:
	path: 数据库文件路径
	db: 指向sqlite句柄的指针,后面对数据库所有的操作都要依赖这个句柄
返回值:
	成功返回0,失败返回错误码(非零值)

sqlite3_close

int   sqlite3_close(sqlite3 *db);
功能:
	关闭sqlite数据库      
返回值:
	成功返回0,失败返回错误码
const  char  *sqlite3_errmsg(sqlite3 *db);
功能:
	打印错误信息        
返回值:
	返回错误信息

不使用回调函数执行SQL语句

sqlite3_get_table


int   sqlite3_get_table(sqlite3 *db, const  char  *sql,  char ***resultp,  int*nrow,  int *ncolumn, char **errmsg);
功能:
	执行SQL操作
参数:
	db:数据库句柄
	sql:SQL语句
	resultp:用来指向sql执行结果的指针
	nrow:满足条件的记录的数目
	ncolumn:每条记录包含的字段数目
	errmsg:错误信息指针的地址
返回值:
	成功返回0,失败返回错误码

举例

下面比如我们要显示student表中所有的数据信息,我们就可以利用sqlite3_get_table()执行语句:

select * from student

实现代码如下:

void do_show_sample(sqlite3 *db)
 {
 	char **result, *errmsg;
	int nrow, ncolumn, i, j, index;

	if (sqlite3_get_table(db, "select * from student", &result, &nrow, &ncolumn, &errmsg) != 0)
	{
		printf("error : %s\n", errmsg);
		sqlite3_free(errmsg);
	}
	index = ncolumn;
	for (i=0; i<nrow; i++)
	{
		for (j=0; j<ncolumn; j++)
		{
			printf("%-8s : %-8s\n", result[j], result[index]);		 
			index++;
		}
		printf("************************\n");
	}
	sqlite3_free_table(result);
	return;
 }

假定当前的表格的数据信息如下:

no name score
4 一口Linux 77.0
5 一口peng 88.0
6 一口wang 99.0
7 一口网 66.0

关于这个函数中出现的这些参数的具体含义,我们可以见下图:

sqlite3编程接口非常多,对于初学者来说,我们暂时只需要掌握常用的几个函数,其他函数自然就知道如何使用了。

数据库

本篇假设数据库为my.db,有数据表student。

no name score
4 一口Linux 89.0

创建表格语句如下:

CREATE TABLE  IF NOT EXISTS student (no integer primary key, name text, score real);

常用函数

sqlite3_open

int   sqlite3_open(char  *path,   sqlite3 **db);
功能:
    打开sqlite数据库
参数:
	path: 数据库文件路径
	db: 指向sqlite句柄的指针
返回值:
	成功返回0,失败返回错误码(非零值)

sqlite3_close

int   sqlite3_close(sqlite3 *db);
功能:
	关闭sqlite数据库      
返回值:
	成功返回0,失败返回错误码
const  char  *sqlite3_errmsg(sqlite3 *db);
功能:
	打印错误信息        
返回值:
	返回错误信息

不使用回调函数执行SQL语句

sqlite3_get_table


int   sqlite3_get_table(sqlite3 *db, const  char  *sql,  char ***resultp,  int*nrow,  int *ncolumn, char **errmsg);
功能:
	执行SQL操作
参数:
	db:数据库句柄
	sql:SQL语句
	resultp:用来指向sql执行结果的指针
	nrow:满足条件的记录的数目
	ncolumn:每条记录包含的字段数目
	errmsg:错误信息指针的地址
返回值:
	成功返回0,失败返回错误码

举例

下面比如我们要显示student表中所有的数据信息,我们就可以利用sqlite3_get_table()执行语句:

select * from student

实现代码如下:

void do_show_sample(sqlite3 *db)
 {
 	char **result, *errmsg;
	int nrow, ncolumn, i, j, index;

	if (sqlite3_get_table(db, "select * from student", &result, &nrow, &ncolumn, &errmsg) != 0)
	{
		printf("error : %s\n", errmsg);
		sqlite3_free(errmsg);
	}
	index = ncolumn;
	for (i=0; i<nrow; i++)
	{
		for (j=0; j<ncolumn; j++)
		{
			printf("%-8s : %-8s\n", result[j], result[index]);		 
			index++;
		}
		printf("************************\n");
	}
	sqlite3_free_table(result);
	return;
 }

假定当前的表格的数据信息如下:

no name score
4 一口Linux 77.0
5 一口peng 88.0
6 一口wang 99.0
7 一口网 66.0

关于这个函数中出现的这些参数的具体含义,我们可以见下图:

在这里插入图片描述

由上图可知:
代码中:

ncolumn = 3
nrow    = 5
result 指向所有的结果组成的字符串数组,
各个具体字符串的下标,图上已经标明。

结合此图再去理解代码,就很容易理解代码的实现原理。

使用回调函数执行SQL语句

sqlite3_exec

typedef  int (*sqlite3_callback)(void *, int, char **, char **);

int   sqlite3_exec(sqlite3 *db, const  char  *sql,  sqlite3_callback callback, void *,  char **errmsg);
功能:
	执行SQL操作
参数:
	db:数据库句柄
	sql:SQL语句,就是我们前面两章用于操作表的增删改查语句
	callback:回调函数
	errmsg:错误信息指针的地址
返回值:
	成功返回0,失败返回错误码

回调函数

typedef  int (*sqlite3_callback)(void *para, int f_num, char **f_value, char **f_name);
功能:
	每找到一条记录自动执行一次回调函数
参数:
	para:传递给回调函数的参数
	f_num:记录中包含的字段数目
	f_value:包含每个字段值的指针数组
	f_name:包含每个字段名称的指针数组
返回值:
	成功返回0,失败返回-1

举例

sqlite3 *db;
char  *errmsg,**resultp;

int callback(void *para, int f_num, char **f_val, char **f_name)
{
	int i;

	for (i=0; i<f_num; i++)
	{
		printf("%-8s", f_val[i]);
	}
	printf("\n");

	return 0;
}

void do_show(sqlite3 *db)
{
	char *errmsg;

	printf("no      name    score\n");
	
	if (sqlite3_exec(db, "select * from student", callback, NULL, &errmsg) != 0)
	{
		printf("error : %s\n", sqlite3_errmsg(db));
	}
	printf("\n");

	return;
}

回调函数方法实现的代码,需要实现一个回调函数:callback。
函数sqlite3_exec()在解析命令"select * from student" ,没获取到一行数据就会调用一次回调函数,
参考上面的表格student,

callback()总共会被调用5次,
f_num 对应结果的列数,为3
f_value 则指向 每一列对应的值组成的字符串数组

假设现在callback是第四次被调用,如下图:
在这里插入图片描述

运行结果

编译需要使用第三方库lsqlite3。

gcc student.c -o run -lsqlite3

运行主页面:
在这里插入图片描述

插入记录:
在这里插入图片描述
显示记录:
在这里插入图片描述
删除记录:
在这里插入图片描述

其他函数

sqlite3 *pdb, 数据库句柄,跟文件句柄FILE很类似
sqlite3_stmt *stmt, 这个相当于ODBC的Command对象,用于保存编译好的SQL语句

sqlite3_exec(), 执行非查询的sql语句
sqlite3_prepare(), 准备sql语句,执行select语句或者要使用parameter bind时,用这个函数(封装了sqlite3_exec)
Sqlite3_step(), 在调用sqlite3_prepare后,使用这个函数在记录集中移动

还有一系列的函数,用于从记录集字段中获取数据,如

sqlite3_column_text(), 取text类型的数据
sqlite3_column_blob(),取blob类型的数据
sqlite3_column_int(),int类型的数据

国际惯例,上完整代码:

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

void do_insert(sqlite3 *db)
{
	int no;
	char name[16];
	float score;
	char sqlstr[128], *errmsg;

	printf("input no : ");
	scanf("%d", &no);
	printf("input name : ");
	scanf("%s", name);
	printf("input score : ");
	scanf("%f", &score);
	sprintf(sqlstr, "insert into student values (%d, '%s', %.1f)", 
	no, name, score);
	#if __DEBUG
	printf("cmd:%s\n",sqlstr);
	#endif
	if (sqlite3_exec(db, sqlstr, NULL, NULL, &errmsg) != 0)
	{
		printf("error : %s\n", sqlite3_errmsg(db));
	}
	else
	{
		printf("insert is done\n");
	}
	printf("\n");

	return;
}

void do_delete(sqlite3 *db)
{
	char *errmsg;
	char sqlstr[128], expression[64];

	printf("input expression : ");
	scanf("%s", expression);//name='ma'
	sprintf(sqlstr, "delete from student where %s", expression);
#if __DEBUG
	printf("cmd:%s\n",sqlstr);
#endif
	if (sqlite3_exec(db, sqlstr, NULL, NULL, &errmsg) != 0)
	{
		printf("error : %s\n", sqlite3_errmsg(db));
	}
	else
	{
		printf("deletet is done\n");
	}
	printf("\n");

	return;
}
 
int callback(void *para, int f_num, char **f_val, char **f_name)
{
	int i;

	for (i=0; i<f_num; i++)
	{
		printf("%-8s", f_val[i]);
	}
	printf("\n");

	return 0;
}

void do_show(sqlite3 *db)
{
	char *errmsg;

	printf("no      name    score\n");

	if (sqlite3_exec(db, "select * from student", callback, NULL, &errmsg) != 0)
	{
		printf("error : %s\n", sqlite3_errmsg(db));
	}
	printf("\n");

	return;
}

 void do_show_sample(sqlite3 *db)
 {
 	char **result, *errmsg;
	int nrow, ncolumn, i, j, index;

	if (sqlite3_get_table(db, "select * from student", &result, &nrow, &ncolumn, &errmsg) != 0)
	{
		printf("error : %s\n", errmsg);
		sqlite3_free(errmsg);
	}
	
	index = ncolumn;

	for (i=0; i<nrow; i++)
	{
		for (j=0; j<ncolumn; j++)
		{
			printf("%-8s : %-8s\n", result[j], result[index]);
			
			 
			index++;
		}
		printf("************************\n");
	}
	sqlite3_free_table(result);

	return;
 }
 

int main()
{
	sqlite3 *db;
	int n;
	int rc = 0;
	char *errmsg;	
	char clean[64];
/* Create SQL statement */
	char sql[] ="CREATE TABLE IF NOT EXISTS STUDENT(" \
	  "NO INT PRIMARY KEY     NOT NULL," \
	  "NAME           TEXT    NOT NULL," \
	  "SCORE            INT     NOT NULL);";


	if (sqlite3_open("my.db", &db) < 0)
	{
		printf("fail to sqlite3_open : %s\n", sqlite3_errmsg(db));
		return -1;
	}
	

  /* Execute SQL statement */
	rc = sqlite3_exec(db, sql, NULL, 0, &errmsg);

	if (rc != SQLITE_OK) {
		fprintf(stderr, "SQL error: %s\n", errmsg);
		sqlite3_free(errmsg);
	} else {
		fprintf(stdout, "Table created successfully\n");
	}

	while ( 1 )
	{
		printf("*********************************************\n");
		printf("1: insert record   \n2: delete record  \n3: show record  \n4: quit\n");
		printf("*********************************************\n");
		printf("please select : "); 
		
		if (scanf("%d", &n) != 1)
		{
			fgets(clean, 64, stdin);
			printf("\n");
			continue;
		}
		switch ( n )
		{
			case 1 :
				do_insert(db);
				break;
			case 2 :
				do_delete(db);
				break;
			case 3 :
				do_show_sample(db);
				break;
			case 4 :
				sqlite3_close(db);
				exit(0);
		}
	}
	return 0;
}

对于初学者只要掌握了实例中的函数,其他函数也就明白如何使用了。

完整代码,请关注公众号「一口Linux」 ,回复sqlite3

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式数据库sqlite3【进阶篇】-如何用C语言操作sqlite3,一文搞懂 的相关文章

  • python 基础

    条件表达式 if 1 gt 2 print 111 elif 2 gt 3 print 222 else print 333 for循环 for i in range 3 10 print i 输出结果 for循环 步长为2 for i i
  • QStyle 自定义QSpinBox外观

    点击查看详细介绍 头文件 ifndef SPINBOX STYLE 1 H define SPINBOX STYLE 1 H include
  • 【高等数学基础知识篇】——函数,极限与连续

    本文仅用于个人学习记录 使用的教材为汤家凤老师的 高等数学辅导讲义 本文无任何盈利或者赚取个人声望的目的 如有侵权 请联系删除 文章目录 一 函数基础知识 1 1 基本初等函数和初等函数 1 2 函数的初等特性 1 3 特殊函数 二 函数题
  • PageHelper的order by方法可替代mybatis中order by必须使用$来避免sql注入

    PageHelper的order by方法可替代mybatis中order by必须使用 来避免sql注入 在my batis中 我们通常使用 字符 来传值 在mybatis中使用order by排序时也习惯性的使用 然后发现sql错误 后
  • 【数学建模笔记 24】数学建模的时间序列模型

    24 时间序列模型 定义 时间序列是按时间顺序排列的 随时间变化且相互关联的数据序列 分析时间序列的方法构成数据分析的一个重要领域 即时间序列分析 一个时间序列往往是以下几类变化形式的叠加 长期趋势变动 T t T t Tt 朝一定方向的变

随机推荐

  • zabbix 通过import批量导入新增主机和批量删除旧的主机

    通过import批量导入新增主机 本文采用zabbix的hosts页面的import 批量导入 zabbix3 2版本批量导入模板 bin bash filename zbx xml echo
  • 『sklearn学习』多种模型预测脸的下半部分的结果对比

    预测脸的下半部分 import numpy as np import matplotlib pyplot as plt from sklearn datasets import fetch olivetti faces from sklea
  • Opencv载取任意长度视频

    文章目录 使用Opencv截取仍意长度视频 使用Opencv截取仍意长度视频 import cv2 import sys def select video input path output path start 1 end 1 input
  • 用Flask搭建一个web应用(三)---拆分models.py&解决循环引用

    在app py同级目录下建立models py models py from flask sqlalchemy import SQLAlchemy from app import db class Article db Model 定义表名
  • Redis缓存详解 -- 转载

    Redis缓存详解 一 缓存穿透 二 缓存雪崩 三 缓存击穿 本篇为转载 只做码届搬运工 Thanks 一 缓存处理流程 前台请求 后台先从缓存中取数据 取到直接返回结果 取不到时从数据库中取 数据库取到更新缓存 并返回结果 数据库也没取到
  • 浏览器发器POST请求

    浏览器按F12或打开开发者工具 在console 控制台 标签页下输入 fetch new Request http localhost 8080 power font getToken method POST headers Conten
  • oracle同比计算

    计算同地区下 同比百分比 select 2020 area no area desc city no city desc area level key id CASE WHEN NVL SUM VAL 19 0 0 THEN 0 ELSE
  • word2vec损失函数

    未优化前损失函数 以CBOW为例 利用softmax层计算出字典V中每个词的概率 再构建交叉熵损失函数 负采样损失函数 直接对词典里的V个词计算相似度并归一化显然是极其耗时的 为此作者提出了层次Softmax和负采样两种损失层 负采样损失函
  • 【笔试】操作系统知识点整理

    一 操作系统概述 1 操作系统的主要功能 进程与处理机管理 作业和进程调度 进程控制和进程通信 存储管理 内存分配 地址映射 内存保护和内存扩充 设备管理 缓冲区管理 设备分配 设备驱动 设备无关性 文件管理 文件存储空间的管理 文件操作的
  • Eclipse 安装阿里巴巴代码规范插件的步骤

    2017年10月14日杭州云栖大会 Java代码规约扫描插件全球首发仪式正式启动 规范正式以插件形式公开走向业界 引领Java语言的规范之路 目前 插件已在云效公有云产品中集成 立即体验 云效 gt 公有云 gt 设置 gt 测试服务 gt
  • c++系列 —— 移动构造函数

    往期地址 c 系列一 c 的封装 c 系列二 c 的继承 c 系列三 继承和多态特性 c 系列四 运算符重载 c 系列五 静态成员和静态类 c 系列六 友元函数和友元类 c 系列七 STL编程之模板template c 系列八 STL编程之
  • 事件循环机制分享

    Event Loop 即事件循环 是JavaScript或Node为解决单线程代码执行不阻塞主进程一种机制 也就是我们所说的异步原理 要了解事件循环机制首先要了解进程 线程 宏任务 微任务 进程 Process 是计算机中的程序关于某数据集
  • 【STM32F0】Keil 查看局部变量显示

    现象 在进行STM32F0开发的时候出现了 调试代码 添加变量Watch时 显示not in scope 处理方式 因为代码开了优化的处理 把优化改到Level0 就可以解决问题
  • 【深度学习】ResNet残差网络 ResidualBlock残差块实现(pytorch)

    文章目录 前言 一 卷积的相关计算公式 复习 二 残差块ResidualBlock复现 pytorch 三 残差网络ResNet18复现 pytorch 四 直接调用方法 五 具体实践 ResNet进行猫狗分类 六 可能报错 6 1 Typ
  • C语言学习:用C语言实现简单的计算器

    用C语言编写一个简单的可以进行加减乘除运算混合运算的计算器的方法 include
  • 解决Chrome浏览器左键双击没反应,无法启动

    打开任务管理器Ctrl aLT DEL 或是在任务栏图标空白处右击 解决Chrome浏览器点击没反应 2 然后 在进程列中 点击表头排序 之后找到chrome exe进程 解决Chrome浏览器点击没反应 3 右击选择后 结束进程 解决Ch
  • rpm -ivh oracle-xe-11.2.0-1.0.x86_64.rpm

    update install the packages for libaio bc and flex view plaincopy to clipboardprint root localhost yum install libaio bc
  • ECharts社区里面的gallery在哪里?ECharts gallery新地址

    学习echarts map发现echarts 社区里面没有gallery了 找了好久 终于找到了 这是新地址 https www makeapie com explore html 赶紧收藏
  • 软件测试用例——三角形

    1 题目 输入三个数a b c分别作为三边的边长构成三角形 通过程序判定所构成的三角形是一般三角形 等腰三角形还是等边三角形时 请为该程序设计测试用例 用等价类划分方法 分析 得出测试用例 用判定表法 条件 1 2 3 4 5 6 7 8
  • 嵌入式数据库sqlite3【进阶篇】-如何用C语言操作sqlite3,一文搞懂

    sqlite3编程接口非常多 对于初学者来说 我们暂时只需要掌握常用的几个函数 其他函数自然就知道如何使用了 数据库 本篇假设数据库为my db 有数据表student no name score 4 一口Linux 89 0 创建表格语句