数据库mysql(学生管理系统)--已写完

数据库:存储文件(数据集合) + 数据库管理系统DBMS(软件)

之前的学生管理系统 关闭终端后 数据就不存在了。因为那时的数据存到了内存上。等进程结束之后,内存就被回收了。

数据库会对数据做加密或者压缩,等需要读的时候会解密。不会占用太多的硬盘空间。

分布式系统-(集群式服务)
在这里插入图片描述
常用数据库
大型数据库:Oracle公司
中型数据库:Server、mySql
小型数据库:

基于linux嵌入式的数据库:SQlite、

数据库的安装

sqlite数据库官网:https://www.sqlite.org

离线安装

sudo dpkg -i sqlite3_3.22.0-1ubuntu0.4_amd64.deb 数据库软件
sudo dpkg -i libsqlite3-dev_3.22.0-1ubuntu0.4_amd64.deb 数据库的库文件

在线安装

sudo apt-get install sqlite3 libsqlite3-dev

如何检查是否已经安装成功:
在终端输入 sqlite3 如果能进入到下面的界面 说明已经装好了
在这里插入图片描述
退出 sqlite3 的终端 输入 .quit 回车

打开数据库文件

注意:如果直接使用sqlite3命令 进入到sqlite的终端操作,那么所有的操作都是在内存上操作的。
当数据库程序退出的时候,所有的数据就都没有了,不会落到硬盘上。 所以,我们操作数据库时,要先打开数据库文件,再操作。

打开数据库文件的方式1:
sqlite3 数据库文件名 数据库文件名可以随便起,但是一般都是以.db 结尾的
打开数据库文件的方式2:
先使用 sqlite3 进入到sqlite3的终端,
然后使用 .open 数据库文件名 来打开数据库文件

数据的操作

系统命令

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

.help  打开帮助手册
.open  打开数据库文件
.exit  退出数据库程序
.quit  退出数据库程序  使用 .q 也可以
.tables  查看数据库中有哪些数据表
.schema  查看表结构(建表语句)
.headers on|off  查询结果是否显示字段名(表头)  on 显示 off 不显示

在这里插入图片描述

SQL语句(重要)

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

常用的sql语句:

//sql语句中关键字是不区分大小写的,一般我们写的时候都写成大写

1.建表语句
    //注意:新创建的数据库文件中是没有数据表的 需要我们自己创建
    CREATE TABLE 表名(字段名1 字段的类型1, 字段名2, 字段类型2);
        字段类型:
            整型:INT INTEGER
            字符串:CHAR TEXT
            不支持浮点型 字符串可表示"3.14"
    例如:
    CREATE TABLE student(id INT, name CHAR, score INTEGER);

2.插入语句
	INSERT INTO student VALUES(1001, "张三", 98);
	//sql语句中的字符串需要用 单引号 '' 或者双引号 "" 引起来
	//注意:上面的插入语句 要求 必须从左到右给每个字段都赋值	
	//如果只想给部分字段赋值,可以使用下面的用法
	INSERT INTO student(id, score) VALUES(1002, 96);//指定字段的赋值
	INSERT INTO student(id, name) VALUES(1003, '王五');

3.查询语句
	SELECT * FROM student; //查询所有记录的所有字段 * 表示所有字段
	SELECT id,score FROM student; //查询所有记录的id和score字段
	SELECT * FROM student WHERE score=70; //查询所有score是70的记录的所有字段
	//WHERE 后面的条件可以使用 AND OR 连接多句
	//AND 并且  OR 或者
	SELECT * FROM student WHERE score=70 AND name='小明';
	SELECT * FROM student WHERE score=70 OR id=1005;
	//查询所有满足score=70并且name="小明"条件的记录的 id字段
	SELECT id FROM student WHERE score=70 AND name='小明';
	
	//对查询结果可以排序
	// ORDER BY 根据那个字段排序
	// ASC 升序  DESC 降序  不写 默认是 升序
	// 查询表中所有记录的所有字段,并将结果根据成绩升序排序
	SELECT * FROM student ORDER BY score ASC;
	// 查询表中所有记录的所有id=1005的字段,并将结果根据成绩降序排序
	SELECT * FROM student WHERE id=1005 ORDER BY score DESC;
 
4.更新记录
	//将表中所有id=1002的记录的name字段更新成 "李四"
	UPDATE student SET name="李四" WHERE id=1002;
	//将表中所有id=1005的记录的name字段更新成 "学霸"且score更新成100
	UPDATE student SET name="学霸",score=100 WHERE id=1005;
	
	//注意:即使没有满足条件的记录,那么该sql语句也不报错
		//只不过没有现象发生,任何记录都不会被更新

5.删除记录
	//删除表中所有name="王五的记录"
	DELETE FROM student WHERE name='王五';
	//删除表中所有score=100或者id=1001的记录
	DELETE FROM student WHERE score=100 OR id=1001;
	
	//注意:即使没有满足条件的记录,那么该sql语句也不报错
		//只不过没有现象发生,任何记录都不会被删除

6.删除表
	DROP TABLE 表名;

//对列的操作了解即可,因为实际开发中表的结构在设计阶段一般都定好了
//不会随便更改,所以对列的操作基本不使用----了解即可
7.给表添加一列
	//给student表中添加一个 sex字段 类型为 TEXT
	ALTER TABLE student ADD COLUMN  sex TEXT;

8.删除表中的一列
	sqlite3 不允许直接删除一列
	1)先创建一张新表
	   CREATE TABLE temp AS SELECT id,name,score FROM student;
	2)删除原来的旧表
	   DROP TABLE student;
	3)对新表重命名
	   ALTER TABLE temp RENAME TO student;

9.主键(PRIMARY KEY)
	在建表的时候可以使用PRIMARY KEY关键字来指定某一个字段为主键
	后面在执行插入语句的时候,主键字段不允许冲突
	如果插入冲突的记录会报错:主键冲突
	例如:
	CREATE TABLE student(id INT PRIMARY KEY, name TEXT, score INT);
	//表示id字段为主键 插入时  id不允许冲突

扩展:
在这里插入图片描述

程序中要有操作数据库的能力,所以要讲API,就可以让程序调函数操作数据库。
这些函数是数据库提供给我们的,不是操作系统提供的。
所以要找这些接口函数的函数说明书–官网
在这里插入图片描述

sqlite3数据库常用的API接口

使用sqlite3提供的函数,编码时需要加头文件 #include <sqlite3.h>
编译时,需要连接sqlite3的库 -lsqlite3
所有API的例子都在下面使用sqlite3数据库实现学生管理系统的例子中

1.打开数据库文件的函数   
	int sqlite3_open(const char *filename,   /* Database filename (UTF-8) */
					sqlite3 **ppDb          /* OUT: SQLite db handle */  );
	功能:
		打开一个数据库文件
	参数:
		filename	数据库文件的名字
		ppDb		操作数据库的指针,句柄。
	返回值:
		成功	SQLITE_OK
		失败	错误码

注意:sqlite3应该是结构体,自己定义一个 sqlite3 *my_db = NULL;


2.获取错误信息的函数
	const char *sqlite3_errmsg(sqlite3* db);
	功能:获取最后一次错误信息描述

3.关闭数据库文件的函数
	int sqlite3_close(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		错误信息的地址
					如果使用了 需要记得使用 sqlite3_free 释放空间
	返回值:
		成功	SQLITE_OK
		失败	错误码
-----------------------关于sqlite3_exec函数的回调函数------------------
	int (*callback)(void* arg, int ncolumn, char **f_value, char **f_name)
	功能:
		得到查询结果
	参数:
		arg			为回调函数传递参数使用的
		ncolumn		记录中包含的字段的数目
		f_value		包含每个字段值的指针数组
		f_name		包含每个字段名称的指针数组
	返回值:
		成功 0
		出错 非0
  
5.获取查询结果的函数
	int sqlite3_get_table(sqlite3 *db, const char *zSql, char ***pazResult, 
				  int *pnRow, int *pnColumn, char **pzErrmsg);
	功能:
		查询数据库,它会创建一个新的内存区域来存放查询的结果信息
		在应用程序处理完结果后 需要调用sqlite3_free_table 释放结果集 否则内存泄漏
	参数:
		db			数据库操作句柄
		zSql		查询数据库的sql语句
		azResult	查询的结果
		nRow		不包含字段名的行数
		nColumn		列数
		errmsg		错误消息 如果使用了记得用 sqlite3_free 释放空间
	返回值:
		成功 SQLITE_OK
		失败 错误码

6.释放sqlite3_get_table函数产生的结果集的函数
	void sqlite3_free_table(char **result);

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

注意!!!
在这里插入图片描述
比如,你在某个路径下打开了sqlite3 zx.db ,系统则会在这个路径下创建 zx.db 的数据库文件。
在这里插入图片描述
学生管理系统完成以下功能: 1.添加 2.修改 3.删除 4.查询 5.退出

查询
程序 去执行查询语句不一定是为了打印到终端。(例:像 输入账号和密码 是为了查询到账号然后登录)
说明 程序去执行查询语句的话,一定要有一块空间去存储查询的结果。具体要对结果如何操作是程序员的事情。想运算就运算,想打印就打印。

查询的两种方式:

1-使用回调函数实现

执行sql语句的函数
	int sqlite3_exec(sqlite3* db, const char *sql, 
				int (*callback)(void*,int,char**,char**),
				void *arg,  char **errmsg);
思考怎样可以在函数内部把数据给到调用者。(返回值是要返回成功或者失败的,所以不能利用返回值)
所以 要求自己封装一个函数 int (*callback)(void*,int,char**,char**)-----------------------关于sqlite3_exec函数的回调函数------------------
	int (*callback)(void* arg, int ncolumn, char **f_value, char **f_name)
	功能:
		得到查询结果
	参数:
		arg			为回调函数传递参数使用的
		ncolumn		记录中包含的字段的数目
		f_value		包含每个字段值的指针数组
		f_name		包含每个字段名称的指针数组
	返回值:成功 0
		   出错 非0


 自己封装的函数 : int callback(void *arg,int n,char **a,char **b)
   int n: select 中有几个字段 就把字段数(列数)通过第二个参数传回来(与表有关 与select后边的字段数量有关,例select id,name,score from student;这种情况n=3)
   char *类型的指针数组,
                                     "id"  "name"  "score"                                  
   s1  char*  |char*  |char*     s2  char* |char* |char*   
       "1001" "zhangsan" "98"
    s1传给形参a,s2传给形参b.
    此时,通过a可以访问记录(数组成员),通过b可以访问所有的字段名。
	注意:自己封装的函数callback()在exec内部并不只是被调用了一次,查询的结果有几条记录就被调用几次。
	                               s1字段值  s2字段名
	int callback(void *arg,int n,char  **a,char **b)
第一次调用          就传这些数据
第二次调用                       s1的指向就变了,s2不变---->就又能获取第二条信息了
 ......             ........   .......    .......


f_value[0] --->"1002"
char *p = "1002";
如果想取出"1002"的话,不能取 *f_value[0] ;
这样取出来的只有1 ,要用atoi()才能把"1002"取出来。

在这里插入图片描述

2-使用 sqlite3_get_table函数实现

获取查询结果的函数

	int sqlite3_get_table(sqlite3 *db, const char *zSql, char ***pazResult, 
				  int *pnRow, int *pnColumn, char **pzErrmsg);
	功能:
		查询数据库,它会创建一个新的内存区域来存放查询的结果信息
		在应用程序处理完结果后 需要调用sqlite3_free_table 释放结果集 否则内存泄漏
	参数:
		db			数据库操作句柄
		zSql		查询数据库的sql语句
		pazResult	查询的结果
		nRow		不包含字段名(表头)的行数
		nColumn		列数
		pzErrmsg    错误消息(类似 errmsg) 如果使用了记得用 sqlite3_free 释放空间
	返回值:
		成功 SQLITE_OK
		失败 错误码
	------------------------------------------------------------------------		
例:
   id     name   score
   1001   张三    98
   1002   李四    100
pazResult	查询的结果 会把查到的所有的结果(包括表头)(如例子一共9)用malloc在内部生成一块空间),这块空间里生成的都是char* 类型的指针数组。(如例子一共9个成员)
   0     1      2    3     4      5     6     7     8  
  char* char* char* char* char* char* char* char* char*
  id    name  score  1001  张三   98   1002  李四  100

这个数组是在函数内部通过malloc的方式产生的。
因为要让我们能访问到这个数组,这个数组的操作空间的大小是 char* 的大小,所以我们要定义一个char**类型的指针p,char **p;所以我们要把p的地址传给pazResult 

我们仅仅知道这个首地址是没用的,这样不知道字段名是多少。也不知道有多少条记录。
所以我们要知道列数nColumn,和行数nRow。

学生管理系统代码

总代码:

#include <head.h>
#include <sqlite3.h>
//select查询的方式有写两种 callback()回调函数 和 sqlite3_get_table()函数
//modify_student()函数使用的第一种方式(比较id)判断是否有某学生存在
//delete_student()函数使用的第二种方式(判断回调函数是否被执行)判断是否有某学生存在

void insert_student(sqlite3 *my_db);
void modify_student(sqlite3 *my_db);
void delete_student(sqlite3 *my_db);
void select_student_1(sqlite3 *my_db);
void select_student_2(sqlite3 *my_db);
void exit_student(sqlite3 *my_db );
int callback(void *arg, int ncolumn, char **f_value, char **f_name);
// 打印菜单的函数
void print_menu()
{
    printf("----------------------------------------\n");
    printf("| 1.添加  2.修改  3.删除  4.查询  5.退出 |\n");
    printf("----------------------------------------\n");
}
// 进程初始化函数
sqlite3 *proc_init()
{
    // 打开数据库文件
    sqlite3 *my_db = NULL;
    int ret = 0;
    if (SQLITE_OK != sqlite3_open("hqyj.db", &my_db))
    {
        printf("sqlite3_open error : errno = [%d] errstr = [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(-1);
    }
    printf("数据库文件打开成功!!\n");
    // 创建表
    char sqlbuff[256] = "CREATE TABLE IF NOT EXISTS student(id int primary key,name char,score int)";
    if (SQLITE_OK != sqlite3_exec(my_db, sqlbuff, NULL, NULL, NULL))
    {
        printf("sqlite3_exec error : errno = [%d] errstr = [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(-1);
    }
    printf("建表成功!!\n");
    return my_db;
}

int main(int argc, const char *argv[])
{
    sqlite3 *my_db = proc_init();
    while (1)
    {
        print_menu();
        int choose = 0;
        printf("请输入你的选择:");
        scanf("%d", &choose);
        if(5 == choose){
            break;
        }
        switch (choose){     
        case 1:
            insert_student(my_db);
            break;
        case 2:
            modify_student(my_db);
            break;
        case 3:
            delete_student(my_db);
            break;
        case 4:
            //select_student_1(my_db);
            select_student_2(my_db);
            break;
        // case 5:
        //     exit_student(my_db);
        default :
            printf("没有此操作,请重新选择");
            break;
        }
    }
    printf("欢迎再次使用学生管理系统!!\n");
    sqlite3_close(my_db);
    return 0;
}

void exit_student(sqlite3 *my_db){
    exit(-1);
}

int flag = 0; //定义一个全局变量,当做打印表头的标志位 
//0 表示需要打印  1 表示不需要打印
//回调函数
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("%10s", f_name[i]);
        }
        printf("\n");
        flag = 1;
    }
    // 在打印记录的值
    for (i = 0; i < ncolumn; i++)
    {
        printf("%10s", f_value[i]);
    }
    printf("\n");
    return 0 ;  //必须要写 否则报错
}

// 查询有两种方式 1-使用回调函数查询--查询所有学员信息
void select_student_1(sqlite3 *my_db)
{
    printf("\n");
    // 组装sql语句
    char sqlbuff[256] = {"SELECT * FROM student"};
    //printf("sqlbuff:[%s]\n", sqlbuff);
    int ret = 0;
    int flag=0;  // 全局变量,为了打印表头
    if (SQLITE_OK != (ret = sqlite3_exec(my_db, sqlbuff, callback, NULL, NULL)))
    {
        printf("sqlite3_exec error : errno = [%d] errstr = [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(-1);
    }
    printf("\n");
    printf("hello\n");
    return;
}

// 查询有两种方式 2-使用sqlite3_get_table()函数实现---查询所有学员信息
void select_student_2(sqlite3 *my_db)
{
   printf("\n");
    // 组装sql语句
    char sqlbuff[256] = {"SELECT * FROM student"};
    //printf("sqlbuff:[%s]\n", sqlbuff);
    int ret = 0;
    int i=0;
    int j=0;
    char **result=NULL;
    int row = 0;
    int column = 0;
    if (SQLITE_OK != (ret = sqlite3_get_table(my_db, sqlbuff, &result, &row,&column, NULL)))
    {
        printf("sqlite3_get_table error : errno = [%d] errstr = [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(-1);
    }
    //处理结果
    //先打印表头
    for (i = 0; i < column; i++){
        printf("%10s", result[i]);
    }
    printf("\n");
    int index=i;
    //再打印记录的值
    for(i=0;i<row;i++){
        for(j=0;j<column;j++){
            printf("%10s", result[index++]);
        }
        printf("\n");
    }
    //释放结果集 防止内存泄露
    sqlite3_free_table(result);
    printf("\n");
    return;
}

void insert_student(sqlite3 *my_db)
{
    int input_id;
    char input_name[32];
    int input_score;
    int ret = 0;
    printf("请输入你要添加的学员信息 [id][name][score]:");
    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);
    if (SQLITE_OK != (ret = sqlite3_exec(my_db, sqlbuff, NULL, NULL, NULL)))
    {
        printf("sqlite3_exec error : errno = [%d] errstr = [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(-1);
    }
    printf("学员信息插入成功!\n");
    return;
}
//判断是否有学院信息的方式1:通过传参比较id来确定
//要有一个回调函数(回调函数必须有返回值,否则调用第二次的时候就会报错)
int exist_student = 0;  //定义全局变量
int find_student_1(void *arg, int ncolumn, char **f_value, char **f_name)
{
    //比较传过来的input_id和f_value[0]中的数值
    //如果相同则说明该学生存在
    if(*(int*)arg == atoi(f_value[0])){
        //则说明该学生存在--存在标志位置1
        exist_student = 1;
    }
    return 0;
}


void modify_student(sqlite3 *my_db)
{
    int input_id = 0;
    char input_name[32] = {0};
    int input_score = 0;
    int ret = 0;
    printf("请输入你要修改的学员id:");
    scanf("%d", &input_id);

    //判断是否有学员信息的方式1:通过传参比较id来确定
    char select_sql[256]="select * from student";
    exist_student = 0;//重置标志位
    //执行select_sql查询语句
    if (SQLITE_OK != (ret = sqlite3_exec(my_db, select_sql, find_student_1, &input_id, NULL)))
    {
        printf("sqlite3_exec error : errno = [%d] errstr = [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(-1);
    }
    //通过判断标志位来判断 该学生是否存在
    if(0 == exist_student){
        //不存在
        printf("查无此人...\n");
        return;
    }
    //逻辑上这里应该 恢复标志位 ,但是我们的代码中使用查询语句之前,每次都会重置标志位
    //所以这里省略了恢复标志位

    printf("请输入你要修改的学员名字和分数 [name][score]:");
    scanf("%s %d", input_name, &input_score);
    // 组装sql语句
    char sqlbuff[256] = {0};
    ret = 0;
    sprintf(sqlbuff, "UPDATE student SET name='%s' , score=%d where id=%d ", input_name, input_score, input_id);
    printf("sqlbuff:[%s]\n", sqlbuff);
    if (SQLITE_OK != (ret = sqlite3_exec(my_db, sqlbuff, NULL, NULL, NULL)))
    {
        printf("sqlite3_exec error : errno = [%d] errstr = [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(-1);
    }
    printf("学员信息修改成功!\n");
    return;
}


int find_student_2(void *arg, int ncolumn, char **f_value, char **f_name)
{
    //只要执行了回调函数就说明学生被找到了
    //修改标志位即可
    exist_student = 1;
    return 0;
}

void delete_student(sqlite3 *my_db)
{
    int input_id = 0;
    int ret = 0;
    printf("请输入你要删除的学员id:");
    scanf("%d", &input_id);

    //判断是否有学员信息的方式2:通过判断回调函数执行的次数来确定
    //这种方式的查询语句需要有条件where
    //原理是:只有在id被找到的情况下才会进入回调函数<=>学生id只有被找到了才能执行回调函数
    char select_sql[256]={0};
    exist_student = 0;//重置标志位
    sprintf(select_sql,"select * from student where id= %d ",input_id);
    //执行select_sql查询语句
    if (SQLITE_OK != (ret = sqlite3_exec(my_db, select_sql, find_student_2, &input_id, NULL)))
    {
        printf("sqlite3_exec error : errno = [%d] errstr = [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(-1);
    }
    //通过判断标志位来判断 该学生是否存在
    if(0 == exist_student){
        printf("查无此人...\n");
        return;
    }

    // 组装sql语句
    char sqlbuff[256] = {0};
    ret=0;
    sprintf(sqlbuff, "DELETE FROM student WHERE id = %d;", input_id);
    //printf("sqlbuff:[%s]\n", sqlbuff);
    if (SQLITE_OK != (ret = sqlite3_exec(my_db, sqlbuff, NULL, NULL, NULL)))
    {
        printf("sqlite3_exec error : errno = [%d] errstr = [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(-1);
    }
    printf("学员信息删除成功!\n");
    return;
}


判断是否有学员信息的两种方式

判断是否有学员信息的方式1:通过传参比较 id 来确定
通过sqlite3_exe()函数的第四个参数arg,传参到callback回调函数中。
本例子通过modify_student()函数来实现的

//判断是否有学院信息的方式1:通过传参比较id来确定
//要有一个回调函数(回调函数必须有返回值,否则调用第二次的时候就会报错)
int exist_student = 0;  //定义全局变量
int find_student_1(void *arg, int ncolumn, char **f_value, char **f_name)
{
    //比较传过来的input_id和f_value[0]中的数值
    //如果相同则说明该学生存在
    if(*(int*)arg == atoi(f_value[0])){
        //则说明该学生存在--存在标志位置1
        exist_student = 1;
    }
    return 0;
}


void modify_student(sqlite3 *my_db)
{
    int input_id = 0;
    char input_name[32] = {0};
    int input_score = 0;
    int ret = 0;
    printf("请输入你要修改的学员id:");
    scanf("%d", &input_id);

    //判断是否有学员信息的方式1:通过传参比较id来确定
    char select_sql[256]="select * from student";
    exist_student = 0;//重置标志位
    //执行select_sql查询语句
    if (SQLITE_OK != (ret = sqlite3_exec(my_db, select_sql, find_student_1, &input_id, NULL)))
    {
        printf("sqlite3_exec error : errno = [%d] errstr = [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(-1);
    }
    //通过判断标志位来判断 该学生是否存在
    if(0 == exist_student){
        //不存在
        printf("查无此人...\n");
        return;
    }
    //逻辑上这里应该 恢复标志位 ,但是我们的代码中使用查询语句之前,每次都会重置标志位
    //所以这里省略了恢复标志位

    printf("请输入你要修改的学员名字和分数 [name][score]:");
    scanf("%s %d", input_name, &input_score);
    // 组装sql语句
    char sqlbuff[256] = {0};
    ret = 0;
    sprintf(sqlbuff, "UPDATE student SET name='%s' , score=%d where id=%d ", input_name, input_score, input_id);
    printf("sqlbuff:[%s]\n", sqlbuff);
    if (SQLITE_OK != (ret = sqlite3_exec(my_db, sqlbuff, NULL, NULL, NULL)))
    {
        printf("sqlite3_exec error : errno = [%d] errstr = [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(-1);
    }
    printf("学员信息修改成功!\n");
    return;
}

判断是否有学员信息的方式2:通过判断 回调函数是否执行 来确定
这种方式的查询语句需要有条件where
原理是:只有在id被找到的情况下才会进入回调函数<=>学生id只有被找到了才能执行回调函数
本例子通过delete_student()函数来实现的


int find_student_2(void *arg, int ncolumn, char **f_value, char **f_name)
{
    //只要执行了回调函数就说明学生被找到了
    //修改标志位即可
    exist_student = 1;
    return 0;
}

void delete_student(sqlite3 *my_db)
{
    int input_id = 0;
    int ret = 0;
    printf("请输入你要删除的学员id:");
    scanf("%d", &input_id);

    //判断是否有学员信息的方式2:通过判断回调函数执行的次数来确定
    //这种方式的查询语句需要有条件where
    //原理是:只有在id被找到的情况下才会进入回调函数<=>学生id只有被找到了才能执行回调函数
    char select_sql[256]={0};
    exist_student = 0;//重置标志位
    sprintf(select_sql,"select * from student where id= %d ",input_id);
    //执行select_sql查询语句
    if (SQLITE_OK != (ret = sqlite3_exec(my_db, select_sql, find_student_2, &input_id, NULL)))
    {
        printf("sqlite3_exec error : errno = [%d] errstr = [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(-1);
    }
    //通过判断标志位来判断 该学生是否存在
    if(0 == exist_student){
        printf("查无此人...\n");
        return;
    }

    // 组装sql语句
    char sqlbuff[256] = {0};
    ret=0;
    sprintf(sqlbuff, "DELETE FROM student WHERE id = %d;", input_id);
    //printf("sqlbuff:[%s]\n", sqlbuff);
    if (SQLITE_OK != (ret = sqlite3_exec(my_db, sqlbuff, NULL, NULL, NULL)))
    {
        printf("sqlite3_exec error : errno = [%d] errstr = [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(-1);
    }
    printf("学员信息删除成功!\n");
    return;
}


关于sqlite_exec的回调函数的结果集

在这里插入图片描述

关于sqlite3_get_table函数产生的结果集

在这里插入图片描述

  • 36
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值