网络编程(八)

网络编程(八)

  • 数据库
    • 数据库的分类
    • 基于嵌入式的数据库
    • 什么是SQLite?
    • 为什么使用SQLite?
    • sqlite3数据库的安装
  • sqlite3中的点命令
    • .open 数据库文件名字
    • .tables [数据库文件名]
    • .schema 表名
    • .database
    • .quit
    • .head on
    • .mode column
  • SQLite数据库中的数据类型
  • SQLite数据库中的约束
  • sqlite3中的SQL语句
    • 建表语句(标注出字段的个数以及类型和约束)
    • 插入语句
    • 查找语句
    • 修改语句
    • 删除语句
    • 删除表
    • 修改表中的字段个数(目前:支持增加一个班新字段)
  • sqlite3中的c/c++接口
    • 打开数据数据sqlite3_open()
    • 执行函数sqlite3_exec()
    • 更适合查找的接口:sqlite3_get_table()
    • 数据库关闭
    • 错误信息的打印

数据库

数据库(Database)是按照数据结构来组织、存储和管理数据的仓库。
每个数据库都有一个或多个不同的 API 用于创建,访问,管理,搜索和复制所保存的数据。
我们也可以将数据存储在文件中,但是在文件中读写数据速度相对较慢。
目的:就是为了永久保存数据
其实就是为了高效安全以及有组织的存储、访问、检索数据!

数据库的分类

关系型数据库管理系统 (RDBMS)、 非关系数据库
比较常用的是关系型数据库!

现在我们使用关系型数据库管理系统(RDBMS)来存储和管理大数据量。所谓的关系型数据库,是建立在
关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。
RDBMS 即关系数据库管理系统(Relational Database Management System)的特点:

  • 1.数据以表格的形式出现
  • 2.每行为各种记录名称
  • 3.每列为记录名称所对应的数据域
  • 4.许多的行和列组成一张表单
  • 5.若干的表单组成databas

基于嵌入式的数据库

基于嵌入式linux的数据库主要有SQLite, Firebird, Berkeley DB, eXtremeDB
Firebird是关系型数据库,功能强大,支持存储过程、SQL兼容等
Berkeley DB中并没有数据库服务器的概念,它的程序库直接链接到应用程序中
eXtremeDB是内存数据库,运行效率高
SQLite关系型数据库,体积小,支持ACID事务
注意:SQLite是一种嵌入式数据库,它的数据库就是一个文件。由于SQLite本身是C写的,而且体积很小,所以,经常被集成到各种应用程序中

什么是SQLite?

SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库一样,您不需要在系统中配置。就像其他数据库,SQLite 引擎不是一个独立的进程,可以按应用程序需求进行静态或动态连接。SQLite 直接访问其存储文件。

为什么使用SQLite?

  • 不需要一个单独的服务器进程或操作的系统(无服务器的)。
  • SQLite 不需要配置,这意味着不需要安装或管理。
  • 一个完整的 SQLite 数据库是存储在一个单一的跨平台的磁盘文件。
  • SQLite 是非常小的,是轻量级的,完全配置时小于 400KiB,省略可选功能配置时小于250KiB。
  • SQLite 是自给自足的,这意味着不需要任何外部的依赖。
  • SQLite 事务是完全兼容 ACID 的,允许从多个进程或线程安全访问。
  • SQLite 支持 SQL92(SQL2)标准的大多数查询语言的功能。
  • SQLite 使用 ANSI-C 编写的,并提供了简单和易于使用的 API。
  • SQLite 可在 UNIX(Linux, Mac OS-X, Android, iOS)和 Windows(Win32, WinCE, WinRT)中运行

sqlite3数据库的安装

在这里插入图片描述
注意:安装完毕sqlite3之后,后续在.c文件中只需引入#include <sqlite3.h>即可使用它提供的API
编译代码链接第三方库:gcc *.c -o app -lsqlite3
如何进入sqlite3的环境?
—》在命令行输入: sqlite3
在这里插入图片描述

sqlite3中的点命令

.open 数据库文件名字

作用:打开数据库文件
存在:直接打开
不存在:新建再打开

.tables [数据库文件名]

作用:查看当前数据库文件中有哪些表
注意:.tables 数据库文件名 —》查看指定的数据库文件中有几张表

.schema 表名

作用:查找指定的表名的字段格式(表中几个字段,字段啥类型,有无约束)

.database

作用:查看当前打开的数据库文件是谁?

.quit

作用:退出当前sqlite3操作环境

.head on

作用:显示时候,带上字段名称

.mode column

作用:显示时候,列对齐

在这里插入图片描述
在这里插入图片描述

SQLite数据库中的数据类型

在这里插入图片描述

SQLite数据库中的约束

在这里插入图片描述

sqlite3中的SQL语句

注意:
1、格式中的[]表示可有可无
2、所有语句末尾均以英文分号结尾
3、语句中的字段表示的所有字符串在书写时,应使用英文的单引号引用!

建表语句(标注出字段的个数以及类型和约束)

如何完整描述一个字段?
—》字段名 类型 [约束];

create table [if not exists] 表名 (字段1 类型 [约束], 字段2 类型 [约束].....);
建一张有关用户信息的表,表名为userInfo
create table if not exists userInfo (name text NOT NULL, sex text check(sex = '男' or sex = '女'));

插入语句

//给全部的字段赋值
insert into 表名 values (值1, 值2…);
注意:
字段中有个别是自增的(想着可以不写),那这时候使用上述格式,不写会报错的
处理办法:假设自增的是ID //ID name pwd
insert into userInfo values (‘zhang’, ‘123456’);//error
insert into userInfo values (null, ‘zhang’, ‘123456’);//ok ID
会自增
//给部分字段赋值
insert into 表名 (字段1,字段2…) values (值1, 值2…);

查找语句

select 字段1, 字段2… from 表名 where 条件;
如果需要查找表中所有信息(所有用户的所有信息):
select * from userInfo;
如果只需查看表中所有用户的密码:
slect pwd from userInfo;
如果只需查看表中用户名为hqyj的密码和ID:
select pwd, ID from userInfo where name = ‘zhang’;
如果查看表中年龄在25岁以上,姓名是王某的所有的且工资在6500以上(模糊查找:like子句 and运算符)
select * from userInfo where age >= 25 and name like ‘王_’ and salary >=6500.0; //and代表且的意思 like子句是模糊查找
将表中所有用户的年龄按照从大到小排序(order by子句–》排序的)
select * from userInfo order by age;//默认是升序
select * from userInfo order by age asc;//默认是升序
select * from userInfo order by age desc;//降序
从表中检索出薪资按照降序排序之后,从低5个人开始的连续8个人的信息(分页查询技术:limit搭配offset)
select * from userInfo order by salary desc limit 8 offset 4;

修改语句

update 表名 set 字段1 = 新值1,字段2 = 新值2… where 条件;
注意:不使用where,则默认将表中的所有字段为自己要求的更改为新值,很危险!!!
update 表名 set 字段1 = 新值1,字段2 = 新值2…;//所有用户的字段全部更改为新值

删除语句

delete from 表名 where 条件;
删除表中姓名为lisi的用户信息
dellete from userInfo where name = ‘lisi’;

删除表

drop table 表名;

修改表中的字段个数(目前:支持增加一个班新字段)

alter table 表名 add column 新字段名 类型 约束;
给userInfo表增加一个薪资字段
alter table userInfo add column salary real check (salary >= 5000.00 and salary <= 10000.00);

sqlite3中的c/c++接口

打开数据数据sqlite3_open()

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

在这里插入图片描述
在这里插入图片描述

执行函数sqlite3_exec()

int sqlite3_exec(sqlite3 *db, const char *sql, sqlite3_callback callback, void *, char **errmsg);
功能:执行SQL操作
db:数据库句柄
sql:SQL语句
callback:回调函数
void *这里代表传递给回调函数的第一个参数。
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_exec在做建表,插入,删除,修改时,回调函数是不会被执行的,因此也没有必要传参,传入NULL即可,只有在做查找时,因为需要关心查找的结果是什么,所以才会进入回调函数内部们进行查看。
在这里插入图片描述
登录业务:
调用sqlite3_exec()按照用户名在数据库中检索用户名对应的密码,用该密码和客户端发送过来需要登录的密码进行比对,一致回应登录成功,否则回应密码错误,如果按照用户名没有查找任何信息,则回应客户端用户不存在。
思考:调用完毕sqlite3_exec()之后,密码如何进行返回?
—》处理办法:将sqlite3_exec的第四个参数和回调函数的第一个参数搭配使用!!!

#include <stdio.h>
#include <sqlite3.h>
#include <string.h>
//回调函数---》当查找到结果时,该回调函数就会被执行一次
int callback(void *arg, int f_num, char **f_value, char **f_name)
{printf("I am callback!\n");//f_num:代表本次查找到的一条记录中字段的个数(和select//后面传入的检索条件有关)//f_value:代表本次查找到的一条记录中每一个字段对应的数值(最重要!)//f_name:代表本次查找到的一条记录中每一个字段的名字printf("本次查询到的记录中字段的个数为:%d个\n",f_num);int i;for(i=0; i<f_num; i++){printf("%s\t",f_name[i]);}printf("\n");printf("--------------------------------\n");for(i=0; i<f_num; i++){printf("%s\t",f_value[i]);}putchar('\n');//完成将f_value的数值进行返回strcpy((char *)arg, f_value[0]);return 0;
}
int main(int argc, const char *argv[])
{//验证:数据库操作中c/c++中API 的使用//打开数据库//定义操作数据库的句柄sqlite3 *db;//int ret = sqlite3_open("MyDataBase.db", &db);int ret = sqlite3_open("./test/MyDataBase.db", &db);if(ret != SQLITE_OK){//打印出错信息printf("打开数据库失败:%s\n",sqlite3_errmsg(db));return -1;}printf("open MyDataBase.db ok!\n");//建表 (userInfo表)//定义保存出错信息(字符串)的变量char *errmsg;char tb_name[50] = "userInfo";ret = sqlite3_exec(db, "create table if not exists userInfo (ID integer PRIMARY KEY AUTOINCREMENT, \name text NOT NULL, pwd text DEFAULT '111111');", NULL, NULL,&errmsg);if(ret != SQLITE_OK){printf("建表失败原因:%s\n",errmsg);//关闭句柄sqlite3_close(db);return -1;}printf("建表 %s 完毕\n",tb_name);//插入语句ret = sqlite3_exec(db, "insert into userInfo values (NULL, 'qianrushi','123456'); \insert into userInfo (name) values ('Java');",NULL, NULL,&errmsg);if(ret != SQLITE_OK){printf("插入数据失败:%s\n",errmsg);sqlite3_close(db);return -1;}printf("insert over!\n");//查找语句//定义地址空间,用来存储ID=2且姓名=Java用户的密码char retPwd[20] = {0};//ret = sqlite3_exec(db, "select pwd from userInfo where name = 'Java'and ID = 2;", \// &callback, retPwd, &errmsg);ret = sqlite3_exec(db, "select pwd from userInfo where name = 'jjjj';",\&callback, retPwd, &errmsg);if(ret != SQLITE_OK){printf("select error:%s\n",errmsg);sqlite3_close(db);return -1;}if(0 == strlen(retPwd)){printf("用户不存在!\n");return -1;}printf("查找到的密码为:%s\n",retPwd);//比较密码char srcpwd[20] = {"111111"};//发送过来的if(0 == strcmp(srcpwd, retPwd)){printf("登陆成功!\n");}else{printf("密码错误!\n");}return 0;
}

思考:查找时,调用sqlite3_exec函数,每查找到一条记录,回调函数就会被执行几次,如果查找多条记录中的字段值,则会比较麻烦,因此sqlite数据库也给我们提供了一个较为方便更适合用于查找的接口:sqlite3_get_table()!!!

更适合查找的接口:sqlite3_get_table()

不使用回调函数执行SQL语句
int sqlite3_get_table(sqlite3 *db, const char *sql, char **resultp,intnrow, int *ncolumn, char **errmsg);
功能:执行SQL操作
db:数据库句柄
sql:SQL语句
resultp:用来指向sql执行结果的指针,数据集(里面存储的是查找到的结果)
nrow:满足条件的记录的数目(值为0代表没有找到相关数据!)
ncolumn:每条记录包含的字段数目
errmsg:错误信息指针的地址
返回值:成功返回0,失败返回错误码
注意:nrow=0是打印的字段名称,从1开始是有效数据的位置,所以想打印出完整的数据记录数,最后要遍历到nrow的!!!。

在这里插入图片描述

#include <stdio.h>
#include <sqlite3.h>
#include <string.h>
int main(int argc, const char *argv[])
{//验证:数据库操作中c/c++中API 的使用//打开数据库//定义操作数据库的句柄sqlite3 *db;//int ret = sqlite3_open("MyDataBase.db", &db);int ret = sqlite3_open("./test/MyDataBase.db", &db);if(ret != SQLITE_OK){//打印出错信息printf("打开数据库失败:%s\n",sqlite3_errmsg(db));return -1;}printf("open MyDataBase.db ok!\n");//建表 (userInfo表)//定义保存出错信息(字符串)的变量char *errmsg;char tb_name[50] = "userInfo";ret = sqlite3_exec(db, "create table if not exists userInfo (ID integer PRIMARY KEY AUTOINCREMENT, \name text NOT NULL, pwd text DEFAULT '111111');", NULL, NULL,&errmsg);if(ret != SQLITE_OK){printf("建表失败原因:%s\n",errmsg);//关闭句柄sqlite3_close(db);return -1;}printf("建表 %s 完毕\n",tb_name);//插入语句ret = sqlite3_exec(db, "insert into userInfo values (NULL, 'qianrushi','123456'); \insert into userInfo (name) values ('Java');",NULL, NULL,&errmsg);if(ret != SQLITE_OK){printf("插入数据失败:%s\n",errmsg);sqlite3_close(db);return -1;}printf("insert over!\n");//查找语句(sqlite3_get_table())//定义存储查找到一条记录结果的地址空间char **resultp;//定义存储查找到的记录的个数的变量int nrow;//定义存储每一条记录的字段个数的变量int ncolumn;//ret = sqlite3_get_table(db, "select * from userInfo;", &resultp, \// &nrow, &ncolumn, &errmsg);ret = sqlite3_get_table(db, "select pwd from userInfo where ID = 100;",&resultp, &nrow, &ncolumn, &errmsg);if(ret != SQLITE_OK){printf("查找信息失败:%s\n",errmsg);sqlite3_close(db);return -1;}//如何得知查找到数据了?if(0 == nrow){//没有找到printf("用户不存在!\n");}else{//找到了//遍历---》从0开始,到nrow-1结束int i,j;//下面双层for循环打印后续视情况而定,可以不选择打印,直接使用数据集中的值进行判断即可!for(i=0; i<=nrow; i++){for(j=0; j<ncolumn;j++){printf("%s\t", resultp[i*ncolumn+j]);}printf("\n");}//比对环节char srcpwd[20] = {"111111"};//假设这是客户端发送的需要登录的客户端的密码//和在数据库中的查找到的密码进行比对if(0 == strcmp(resultp[1], srcpwd)){printf("登陆成功!\n");}else{printf("密码错误!\n");}}return 0;
}

数据库关闭

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

错误信息的打印

const char *sqlite3_errmsg(sqlite3 *db);
返回值:返回错误信息

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/340124.html

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

相关文章

【Linux】Linux环境基础开发工具_4

文章目录 四、Linux环境基础开发工具gcc和g动静态库的理解 make和MakefileLinux小程序---进度条 未完待续 四、Linux环境基础开发工具 gcc和g 动静态库的理解 动态库的优点&#xff1a;比较节省资源&#xff0c;不会出现太多重复代码。 动态库的缺点&#xff1a;对库的依赖性…

C语言 数组——数组的其他应用之筛法求素数

目录 数组的其他应用 求100以内的所有素数 筛法求100以内的所有素数 自顶向下、逐步求精设计算法 数组的其他应用 求100以内的所有素数 筛法求100以内的所有素数 自顶向下、逐步求精设计算法 step 1&#xff1a;设计总体算法  初始化数组a&#xff0c;使a[2]2, a[3]3,..…

算法 java 排序和查找

排序和查找 冒泡排序&#xff08;稳定&#xff09;选择排序&#xff08;不稳定&#xff09;插入排序&#xff08;稳定&#xff09;希尔排序&#xff08;不稳定&#xff09;归并排序&#xff08;稳定&#xff09;快速排序&#xff08;不稳定&#xff09;堆排序计数排序桶排序基数…

C++设计模式——Adapter适配器模式

一&#xff0c;适配器模式简介 适配器模式是一种结构型设计模式&#xff0c;用于将已有接口转换为调用者所期望的另一种接口。 适配器模式让特定的API接口可以适配多种场景。例如&#xff0c;现有一个名为"Reader()"的API接口只能解析txt格式的文件&#xff0c;给这…

【AR开发-开源框架】使用Sceneform-EQR快速开发AR应用,当前接入了AREngine、ORB-SLAM,可快速地适配不同的安卓设备

Sceneform-EQR Sceneform 概览 Sceneform是一个3D框架&#xff0c;具有基于物理的渲染器&#xff0c;针对移动设备进行了优化&#xff0c;使您可以轻松构建增强现实应用程序&#xff0c;而无需OpenGL。 借助 Sceneform&#xff0c;您可以轻松地在 AR 应用和非 AR 应用中渲染…

Caused by: java.rmi.server.ExportException: Port already in use: 1100;解决方案

Caused by: java.rmi.server.ExportException: Port already in use: 1100; 根据端口号找占用程序的进程号 netstat -ano|findstr 1100 最右边那个数字就是进程号 在任务管理器中 详细信息&#xff0c;点击pid即可按照进程号排序&#xff0c;找到相应的进程&#xff0c;判断…

盲盒小程序预售机制的设计与实施

随着盲盒市场的不断发展&#xff0c;预售机制逐渐成为商家吸引用户、提升销售额的重要手段。本文将探讨盲盒小程序预售机制的设计与实施&#xff0c;以帮助商家更好地满足用户需求并优化库存周转率。 一、预售机制设计原则 在设计预售机制时&#xff0c;商家需要遵循以下几个…

基于 vue-element-template 框架添加 tagsview

1. 需求 vue-element-template 是一个基础模板&#xff0c;默认没有 tagsview。所以要手动添加。 参考最全面的集成方案框架 vue-element-admin &#xff0c;拷贝和修改相关文件到你的项目中。 2. 修改 复制如下文件或文件夹 \src\layout\components\TagsView\src\store\mo…

Docker基础篇之本地镜像发布到阿里云

文章目录 1. 本地镜像发布到阿里云的流程2. 阿里云开发平台3. 将自己的本地镜像推送到阿里云 1. 本地镜像发布到阿里云的流程 阿里云ECS Docker生态如下图所示&#xff1a; 2. 阿里云开发平台 在控制台找到容器和镜像服务&#xff1a; 然后创建一个个人实例&#xff1a; 下面…

号称超级增程电动,领克07EM-P带来技术变革?

近年来&#xff0c;自主品牌在新能源汽车领域百花齐放&#xff0c;尤其是在混合动力市场上&#xff0c;比亚迪的DM-i技术引领了风潮&#xff0c;秦L的一经亮相&#xff0c;整个车圈都沸腾了&#xff0c;“超级混动”的概念深入人心。 各大自主品牌都有了自己的混动平台和技术。…

实战

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 实战一&#xff1a;大乐透号码生成器 使用Random模块模拟大乐透号码生成器。选号规则为&#xff1a;前区在1&#xff5e;35的范围内随机产生不重复的…

大数据—元数据管理

在大数据环境中&#xff0c;元数据管理是确保数据资产有效利用和治理的关键组成部分。元数据是描述数据的数据&#xff0c;它提供了关于数据集的上下文信息&#xff0c;包括数据的来源、格式、结构、关系、质量、处理历史和使用方式等。有效的元数据管理有助于提高数据的可发现…

【Qt】win10,QTableWidget表头下无分隔线的问题

1. 现象 2. 原因 win10系统的UI样式默认是这样的。 3. 解决 - 方法1 //横向表头ui->table->horizontalHeader()->setStyleSheet("QHeaderView::section{""border-top:0px solid #E5E5E5;""border-left:0px solid #E5E5E5;""bord…

【C语言】位段(结构体实现位段)

目录 一、位段的定义 二、位段的声明 三、位段的内存分配 四、位段在内存中的存储方式 五、位段的优点 六、位段的跨平台问题 七、位段的应用 八、位段使用的注意事项 一、位段的定义 信息的存取一般以字节为单位。实际上&#xff0c;有时存储一个信息不必用一个或多个字…

经典获奖案例 | 度小满互联网金融开源软件治理解决方案

近日&#xff0c;广东省粤港澳合作促进会金融专业委员会和粤港澳大湾区金融创新研究院在广州联合举办“2024年粤港澳大湾区数智金融峰会暨第二届金融创新优秀应用案例与解决方案技术成果授牌仪式”。《度小满互联网金融开源软件治理解决方案》从数百个申报项目中脱颖而出&#…

Java面试八股之死锁和饥饿的区别

死锁和饥饿的区别 定义与现象&#xff1a; 死锁&#xff08;Deadlock&#xff09;是指两个或多个线程互相等待对方持有的资源而无法继续执行的情况。每个线程至少持有一个资源&#xff0c;并尝试获取另一个由其他线程持有的资源&#xff0c;从而形成一个循环等待的僵局&#…

Python 图书馆管理系统(MySQL数据库) 有GUI界面 【含Python源码 MX_032期】

使用python3&#xff0c;PyQt5&#xff0c;MySQL数据库搭建 主要功能&#xff1a; 用户注册、登录、修改密码、用户管理存储图书信息、采购增加和淘汰删除功能、租借功能实现图书采购、淘汰、租借功能。实现查询图书信息、采购和淘汰、库存、和租借情况实现统计图书的采购、库…

多输入多输出非线性对象的模型预测控制—Matlab实现

本示例展示了如何在 Simulink 中设计多输入多输出对象的闭环模型预测控制。该对象有三个操纵变量和两个测量输出。 一、非线性对象的线性化 运行该示例需要同时安装 Simulink 和 Simulink Control Design。 % 检查是否同时安装了 Simulink 和 Simulink Control Design if ~m…

【Python】【matLab】模拟退火算法求二元高次函数最小值

一、目标函数 求二元高次函数的最小值。目标函数选择&#xff1a; 用于测试算法的简单的目标函数&#xff1a; 二、Python代码实现 import numpy as np# 目标函数&#xff08;2变量&#xff09; def objective_function(x):return x[0] ** 2 2 * x[0] - 15 4 * 4 * 2 * x[…

Flutter:革新移动开发的开源框架

在今天的移动应用开发领域&#xff0c;Flutter 已成为最受欢迎的开源框架之一。由 Google 开发并在 2017 年发布&#xff0c;Flutter 允许开发者使用单一代码库来构建跨平台的高性能应用&#xff0c;有效地覆盖了 iOS 和 Android 两大平台。接下来&#xff0c;我们将深入探索 F…