【网络编程】

数据库

sqlite官网:https://www.sqlite.org/index.html

数据库的安装

离线安装:

sudo  dpkg  -i  libsqlite3-dev_3.22.0-1ubuntu0.4_amd64.deb
sudo  dpkg  -i  sqlite3_3.22.0-1ubuntu0.4_amd64.deb

在线安装:

sudo  apt-get  install  sqlite3
sudo  apt-get  install  libsqlite3-dev

如何检查是否安装成功
在终端输入 sqlite3 ,直接回车,如果能看到下面的sqlite3的命令行,就说明已经装好了
在这里插入图片描述
输入 .quit 回车 退出数据库

打开数据库文件

如果不打开数据库文件,直接通过sqlite3的终端操作,所有的操作都是在内存上操作,并没有把数据落到硬盘上,所以当数据库程序退出时,数据就没了。

打开数据库文件的方式1:

sqlite3 数据库文件名
注意:数据库文件名随便起,一般都以 .db 结尾
这种方式如果文件存在 则直接打开使用 如果不存在 则新建并打开使用

打开数据库文件的方式2:

先使用 sqlite3 进入到sqlite数据的程序的终端
然后 使用 .open 数据库文件名 方式打开

数据库的操作

系统命令

不同的数据库软件 一般系统命令都是不一样的,
sqlite3数据库的系统命令是以 . 开头的 结尾不能加分号

.help   获取帮助信息
.exit   退出数据库程序
.quit   退出数据库程序   .q 也可以
.tables  查看数据库文件中有哪些数据表
.schema  查看数据表的建表语句(表的结构)
.headers on|off  查询结果是否显示表头信息
关系型数据库表的结构

在这里插入图片描述

SQL语句

只要是关系型数据库,SQL语句都是通用的
SQL要求 不能以.开头 必须有分号结尾
常用的sql语句

//sql语句中 关键字不区分大小写 但是一般情况下 我们都把关键字大写

1.建表语句
    打开新的数据库文件时,里面是没有数据表的,需要我们自己创建
	
    CREATE TABLE 表名(字段名1 字段类型1, 字段名2 字段类型2, ...);
				字段的类型:
					整数:INT  INTEGER
					字符串:CHAR  TEXT
	例如:
	CREATE TABLE student(id INT, name TEXT, score INTEGER);

2.向表中插入数据
	//这种插入方式 必须给每个字段都赋值 从左到右依次赋值
	//SQL语句中使用字符串时  需要用 单引号 或者 双引号引起来
	INSERT INTO student VALUES(1001, "zhangsan", 98);
	
	//这种方式可以指定只给几个字段赋值 根据给定的字段从左到右依次赋值
	INSERT INTO student(id, name) VALUES(1002, 'lisi');

3.查询表中的记录
	SELECT * FROM student;			//查询表中所有记录的所有字段  * 所有字段
 	SELECT name FROM student;		//只查询表中所有记录的 name 字段
	SELECT name,score FROM student;	//只查询表中所有记录的 name 和 score 字段
	
	//查询表中score=98分的所有记录的所有字段
	SELECT * FROM student WHERE score=98;

	//条件如果是字符串 也得用 单引号 或者 双引号 引起来
	SELECT * FROM student WHERE name="zhangsan";
	
	//如果有多个条件 也可以使用 AND 或者 OR 连接 AND 表示并且  OR 表示或者
	SELECT * FROM student WHERE score=98 AND name="zhangsan";
	SELECT * FROM student WHERE score=98 OR name="lisi";
	
	//对查询的结果进行排序
	//ORDER BY 根据哪个字段排序
	//ASC 升序  DESC  降序   默认不写是升序
	SELECT * FROM student ORDER BY score DESC;//将查询结果根据成绩降序排序

4.更新表中的记录
	//将id为1001的记录中 name字段改成 "xiaoming"
	UPDATE student SET name="xiaoming" WHERE id=1001;
	
	//如果要修改多个字段的值 可以用逗号分隔
	UPDATE student SET name="xiaohong",score=80 WHERE id=1005;

	//注意:即使没有符合条件的记录 也不报错 只不过没有任何事情发生

5.删除表中的记录
	//删除表中 id=1001 的记录
	DELETE FROM student WHERE id=1001;
	
	//和更新同理 即使条件不成立 也不会报错 只是没有事情发生

6.删除数据表
	DROP TABLE 表名;

//关于列的操作 了解即可 因为表的结构在设计阶段一般就都定好了,不会更改
7.在表中添加一个字段
	//在表student中添加一个新的字段 sex 类型为 CHAR
	ALTER TABLE student ADD COLUMN sex CHAR;

8.删除一个字段
	sqlite3 不允许直接删除字段的 可以中转达到目的
	1> 先创建一张新的表
		CREATE TABLE temp AS SELECT id,name FROM student;
	2> 删除原来的旧表
		DROP TABLE student;
	3> 将新表重命名为旧表的名字
		ALTER TABLE temp RENAME TO student;

9.主键 ----重要
	//PRIMARY KEY 在建表的时候可以使用该关键字指定某个字段为主键
	//插入数据时,主键不允许冲突的  ----插入冲突的数据 会报错  主键冲突
	CREATE TABLE student(id INT PRIMARY KEY, name CHAR, score INT);

sqlite3常用的API接口

查看函数的说明 在 sqlite的官网查看
编码时需要加头文件 #include <sqlite3.h>
编译时需要链接库文件 -lsqlite3

例子都在下面使用数据库实现学生管理系统的例子中。

1.打开数据库文件的函数
    int sqlite3_open(const char *filename,   /* Database filename (UTF-8) */
                sqlite3 **ppDb          /* OUT: SQLite db handle */  );
    	功能:
        打开一个数据库
    参数:
        filename	数据库名字(不写路径默认的就是当前路径下寻找)
    					存在直接打开 不存在则新建并打开
    		ppDb      	操作数据库的指针,句柄。
	返回值:
		成功 SQLITE_OK
		失败 错误码

2.关闭数据库的函数
	int sqlite3_close(sqlite3* db);
	参数:数据的句柄

3.获取错误信息的函数
	const char *sqlite3_errmsg(sqlite3* db);
	功能:获取错误信息的描述(最后一次的出错信息)
	参数:数据的句柄
	返回值:指向错误信息字符串的指针

4.执行SQL语句的函数
	int sqlite3_exec(sqlite3* db, const char *sql, 
				int (*callback)(void*,int,char**,char**),
				void *arg,  char **errmsg);
	功能:
		执行一条sql语句
	参数:
		db			数据库的句柄指针
		sql			将要被执行sql语句
		callback	回调函数, 只有在查询语句时,才使用
		arg  		为callback 传参的, 只有在查询语句时,才使用
		errmsg 		错误信息的地址
					如果使用了最后一个参数 还得手动释放错误信息占用的空间
	返回值:
		成功 SQLITE_OK
		出错 错误码
------------------------关于 sqlite3_exec的回调函数------------------
	int (*callback)(void* arg, int ncolumn, char** f_value, char** f_name)
	功能:
		得到查询结果
	参数:
		arg  	 为回调函数传递参数使用的
		ncolumn  记录中包含的字段的数目
		f_value  包含每个字段值的指针数组
		f_name   包含每个字段名称的指针数组
	返回值:
		成功 SQLITE_OK
		出错 非0

5.释放错误信息的空间
	void sqlite3_free(void *p);

6.查询数据库的函数
	int sqlite3_get_table(sqlite3 *db, const char *zSql, char ***pazResult, 
				  int *pnRow, int *pnColumn, char **pzErrmsg);
	功能:
		查询数据库,它会创建一个新的内存区域来存放查询的结果信息
	参数:
		db		数据库操作句柄
		sql		数据库的sql语句
		pazResult 查询的结果
		nRow	行数 不包括字段名的行数
		nColumn	列数
		errmsg	错误消息 如果使用了 也得使用 sqlite3_free 来释放空间
	返回值:
		成功 SQLITE_OK
		出错 错误码

7.释放由sqlite3_get_table产生的结果集
	void sqlite3_free_table(char **result);

使用数据库实现学生管理系统

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

#define DATABASE "hqyj.db"

//打印菜单的函数
void print_menu(){
	printf("----------------------------------------\n");
	printf("| 1.添加  2.修改  3.查找  4.删除  5.退出 |\n");
	printf("----------------------------------------\n");
	printf("input your choose : ");
}

//程序初始化的函数
sqlite3 *process_init(){
	sqlite3 *my_db = NULL;
	char *errstr = NULL;
	int ret = 0;
	//打开数据库文件
	if(SQLITE_OK != (ret = sqlite3_open(DATABASE, &my_db))){
		printf("打开数据库文件失败 :errcode[%d], errstr[%s]\n", ret, sqlite3_errmsg(my_db));
		exit(-1);
	}
	printf("打开数据库文件成功..\n");
	//尝试建立数据表
	//组建sql语句  代码中组装的sql语句 无需在结尾加 ;
	// IF NOT EXISTS 表示如果表存在则直接使用 不存在在执行创建的语句
	char sqlbuff[256] = "CREATE TABLE IF NOT EXISTS student(id INT PRIMARY KEY, name TEXT, score INT)";
	//执行sql语句
	if(SQLITE_OK != (ret = sqlite3_exec(my_db, sqlbuff, NULL, NULL, &errstr))){
		printf("建表失败 errcode[%d], errstr[%s]\n", ret, errstr);
		exit(-1);
	}
	printf("尝试建表成功..\n");

	//如果用了 sqlite3_exec 的第五个参数 记得释放空间
	sqlite3_free(errstr);

	return my_db;
}

//添加学员信息的函数
void insert_student(sqlite3 *my_db){
	int input_id = 0;
	char input_name[32] = {0};
	int input_score = 0;
	printf("请输入新学员的信息(id INT, name TEXT, score INT) : ");
	scanf("%d%s%d", &input_id, input_name, &input_score);
	//组装sql语句
	char sqlbuff[256] = {0};
	sprintf(sqlbuff, "INSERT INTO student VALUES(%d, '%s', %d)", \
					input_id, input_name, input_score);
	//注意 数据库代码出现错误 第一件事儿 先把要执行的sql语句打印出来 !!!
	//printf("yangfs sqlbuff:[%s]\n", sqlbuff);
	//执行sql语句
	int ret = 0;
	if(SQLITE_OK != (ret = sqlite3_exec(my_db, sqlbuff, NULL, NULL, NULL))){
		printf("学员信息插入失败: errcode[%d], errstr[%s]\n", ret, sqlite3_errmsg(my_db));
        return;
	}
	printf("学员信息插入成功..\n");
	return;
}

//修改学员信息的函数  根据学员的id 修改 name 和 score
void modify_student(sqlite3 *my_db){
	int input_id = 0;
	printf("请输入要修改的学员的id(INT):");
	scanf("%d", &input_id);
	char input_name[32] = {0};
	int input_score = 0;
	printf("请输入新的信息(name TEXT, score INT) : ");
	scanf("%s%d", input_name, &input_score);
	//组装sql语句
	char sqlbuff[256] = {0};
	sprintf(sqlbuff, "UPDATE student SET name='%s',score=%d WHERE id=%d", \
					input_name, input_score, input_id);
	//执行sql语句
	int ret = 0;
	if(SQLITE_OK != (ret = sqlite3_exec(my_db, sqlbuff, NULL, NULL, NULL))){
		printf("学员信息修改失败: errcode[%d], errstr[%s]\n", ret, sqlite3_errmsg(my_db));
        return;
	}
	printf("学员信息修改成功..\n");
	return;
}

int flag = 0; //打印表头的标志位 0 需要打印  1 不需要打印

//sqlite3_exec的回调函数 每查询到一条记录 callback就会被调用一次
int callback(void* arg, int ncolumn, char** f_value, char** f_name){
	//打印表头
	int i = 0;
	if(0 == flag){
		for(i = 0; i < ncolumn; i++){
			printf("%20s", f_name[i]);
		}
		printf("\n");
		flag = 1;
	}

	//再打印记录的值
	for(i = 0; i < ncolumn; i++){
		printf("%20s", f_value[i]);
	}
	printf("\n");

	return 0;//必须要写return  否则报错 query aborted
}

//查找学员信息的函数 使用callback回调函数实现
void search_student_1(sqlite3 *my_db){
	printf("\n");
	//组装sql语句
	char sqlbuff[256] = "SELECT * FROM student";
	//执行sql语句
	int ret = 0;
	flag = 0;//重置打印表头的标志位
	if(SQLITE_OK != (ret = sqlite3_exec(my_db, sqlbuff, callback, NULL, NULL))){
		printf("学员查询删除失败: errcode[%d], errstr[%s]\n", ret, sqlite3_errmsg(my_db));
        return;
	}
	printf("学员信息查询成功..\n");
	printf("\n");
	return;
}

//查找学员信息的函数 使用sqlite3_get_table回调函数实现
void search_student_2(sqlite3 *my_db){
	printf("\n");
	//组装sql语句
	char sqlbuff[256] = "SELECT * FROM student";
	//执行sql语句
	int ret = 0;
	char **presult = NULL;
	int row = 0;
	int column = 0;
	if(SQLITE_OK != (ret = sqlite3_get_table(my_db, sqlbuff, &presult, &row, &column, NULL))){
		printf("学员查询删除失败: errcode[%d], errstr[%s]\n", ret, sqlite3_errmsg(my_db));
        return;
	}
	//处理查询到的结果
	//先打印表头
	int i = 0;
	int j = 0;
	for(i = 0; i < column; i++){
		printf("%20s", presult[i]);
	}
	printf("\n");
	int index = i;
	//再打印字段的值
	for(i = 0; i < row; i++){
		for(j = 0; j < column; j++){
			printf("%20s", presult[index++]);
		}
		printf("\n");
	}

	//释放有sqlite3_get_table产生的结果集
	sqlite3_free_table(presult);

	printf("学员信息查询成功..\n");
	printf("\n");
	return;
}

//删除学员信息的函数  根据学员的id 删除学员的信息
void delete_student(sqlite3 *my_db){
	int input_id = 0;
	printf("请输入要删除的学员的id(INT):");
	scanf("%d", &input_id);
	//组装sql语句
	char sqlbuff[256] = {0};
	sprintf(sqlbuff, "DELETE FROM student WHERE id=%d", input_id);
	//执行sql语句
	int ret = 0;
	if(SQLITE_OK != (ret = sqlite3_exec(my_db, sqlbuff, NULL, NULL, NULL))){
		printf("学员信息删除失败: errcode[%d], errstr[%s]\n", ret, sqlite3_errmsg(my_db));
        return;
	}
	printf("学员信息删除成功..\n");
	return;
}

int main(int argc, const char *argv[])
{
	printf("欢迎使用 HQYJ 学生管理系统..\n");
	printf("程序初始化中..\n");
	sqlite3 *my_db = process_init();
	int choose = 0;
	while(1){
		print_menu();
		scanf("%d", &choose);
		switch(choose){
			case 1:
				insert_student(my_db);
				break;
			case 2:
				modify_student(my_db);
				break;
			case 3:
				//search_student_1(my_db);
				search_student_2(my_db);
				break;
			case 4:
				delete_student(my_db);
				break;
		}
		if(5 == choose){
			break;
		}
	}

	//关闭数据库文件
	sqlite3_close(my_db);

	printf("欢迎下次使用本系统..\n");

	return 0;
}

关于callback回调函数的结果集

以表中记录如下图所示的情况为例, 执行 “SELECT * FROM student”
在这里插入图片描述
在这里插入图片描述

关于sqlite3_get_table函数产生的结果集

以表中记录如下图所示的情况为例, 执行 “SELECT * FROM student”
在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值