linux C Mysql数据库增删改查(CURD)操作
2021/12/17 2:17:00
本文主要是介绍linux C Mysql数据库增删改查(CURD)操作,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
功能介绍
本文的目的主要是接收如何使用mysql提供的C API来实现在linux下的增删改查操作(CURD),没什么技术难点,适用于初学者。主要有以下几个功能:
1.数据的插入
2.数据的查询
3.使用存储过程删除数据 (多条数据库的组合)
4.实现图片的存储和读取操作
这里不对数据库语句和存储过程进行说明,希望读者具有增删改查和存储过程的基本知识。
环境说明
1.实验环境
操作系统: ubuntu16.04
数据库版本:MYSQL5.7
2.环境搭建
(1).安装数据库
命令:sudo apt-get install mysql-server-5.7
(2).安装libmysqlclient开发环境
命令:sudo apt-get install libmysqlclient-dev
说明:如果要使用C语言来操作数据库,这个是必不可少的,头文件mysql.h是和这个libmysqlclient进行绑定的。
(3).安装mysql客户端工具(navicate或者workbench等)
我是在window下操作的,安装navicat
如果是在linux环境下安装workbench: sudo apt-get install mysql-workbench
(3)其他环境
如果是在Windows下使用的是虚拟机环境,最好是要有ssh工具,比如Xshell等。另外还建议使用Samba服务,实现window和linux下的文件共享,具体操作自行百度。
3.准备工作
(1)打开mysql服务:sudo service mysql start
(2)进入到数据库服务: sudo mysql -uroot -p 然后输入密码
(3) 创建admin用户,密码为123456: create user ‘admin’@’%’ identified by ‘123456’; 这里的作用是方便mysql客户端工具连接到mysql服务器。
(4)对admin用户进行授权(为了方便,我们选择授予所有权限,授权后重启mysql服务): grant all on . to ‘admin’@’%’ identified by ‘123456’;
说明:0.0.0.0代表所有地址都可以访问服务器.具体sql权限的问题请自行百度。
注意:(3)和(4)操作都是在mysql命令下操作, 其中第4步,在网上找了很多授权方式都不行,不知道是不是版本原因,另外如果不新建用户,使用root,需要修改配置文件将bind-address修改为0.0.0.0,否则不能进行远程连接。
(4)使用mysql客户端工具进行操作,连接服务器。
接下来就使用Navicat客户端进行操作 创建数据库和表语句
CREATE DATABASE IF NOT EXISTS KING_DB; USE KING_DB; CREATE TABLE IF NOT EXISTS TBL_USER( U_ID INT PRIMARY KEY AUTO_INCREMENT, U_NAME VARCHAR(20), U_GENDER VARCHAR(8) ); INSERT TBL_USER(U_NAME, U_GENDER) VALUES('Lee', 'man'); SELECT * FROM TBL_USER; #MYSQL 5.6默认引入了安全机制,对于删除操作, #会影响多行的(比如按用户名删除),默认是无法删除的 #SET SQL_SAFE_UPDATES=0; #设置操作模式为非安全 #DELETE FROM TBL_USER WHERE U_NAME = 'King'; #SET SQL_SAFE_UPDATES=1;#设置操作模式为安全模式 DROP PROCEDURE IF EXISTS PROC_DELETE_USER; #使用存储过程来删除用户 DELIMITER $$ #5.6后引入DELMITER告诉使用什么来结束存储过程,$$可以替换为其他的 CREATE PROCEDURE PROC_DELETE_USER(IN UNAME VARCHAR(20)) BEGIN SET SQL_SAFE_UPDATES=0; #设置操作模式为非安全 DELETE FROM TBL_USER WHERE U_NAME = UNAME; SET SQL_SAFE_UPDATES=1;#设置操作模式为安全模式 END$$ #调用存储过程的方式 CALL PROC_DELETE_USER('Lee'); #删除所有用户为Lee的行 alter table TBL_USER add U_IMG BLOB;
上面就是创建好了数据库、表、存储过程。下面就用代码来对数据库进行增删改查的操作。
代码实现
代码说明
里面涉及到的数据库API ,都可以在mysql的帮助文档C API部分找到,关于帮助文档的用法,首先随便输入一个API,然后找到了对应的,然后再使用CTRL+F,进行搜索,就可以看到相应API的使用方法
图片存储和读取
(1)存储图片:首先将图片文件读取到buffer中,然后将buffer存储到数据库中
(2)从数据库中获取图片:首先见图片文件读取到buffer中,然后将buffer写入到文件中
源代码
#include <stdio.h> #include <string.h> #include <mysql.h> #define KING_DB_SERVER_IP "192.168.179.128" #define KING_DB_SERVER_PORT 3306 #define KING_DB_USERNAME "admin" #define KING_DB_PASSWORD "123456" #define KING_DB_DEFAULTDB "KING_DB" //数据库名称 #define SQL_INSERT_TBL_USER "INSERT TBL_USER(U_NAME, U_GENDER) VALUES('King', 'man');" #define SQL_SELECT_TBL_USER "SELECT * FROM TBL_USER;" #define SQL_DELETE_TBL_USER "CALL PROC_DELETE_USER('King')" #define SQL_INSERT_IMG_USER "INSERT TBL_USER(U_NAME, U_GENDER, U_IMG) VALUES('King', 'man', ?);" #define SQL_SELECT_IMG_USER "SELECT U_IMG FROM TBL_USER WHERE U_NAME='King';" #define FILE_IMAGE_LENGTH (64*1024) //存放图片的buffer // C U R D --> // int king_mysql_select(MYSQL *handle) { // // mysql_real_query --> sql if (mysql_real_query(handle, SQL_SELECT_TBL_USER, strlen(SQL_SELECT_TBL_USER))) { printf("mysql_real_query : %s\n", mysql_error(handle)); return -1; } // store --> MYSQL_RES *res = mysql_store_result(handle);//存放结果集 if (res == NULL) { printf("mysql_store_result : %s\n", mysql_error(handle)); return -2; } // rows / fields int rows = mysql_num_rows(res);//结果集的行数 printf("rows: %d\n", rows); int fields = mysql_num_fields(res);//结果集的列数 printf("fields: %d\n", fields); // fetch MYSQL_ROW row;//1行数据的“类型安全”表示。 while ((row = mysql_fetch_row(res))) {//从结果集中获取下一行,如果没有行了,则返回NULL int i = 0; for (i = 0;i < fields;i ++) { printf("%s\t", row[i]);//row[0]-row[fields-1]为某一行的所有数据项 } printf("\n"); } //释放由mysql_store_result()、mysql_use_result()、mysql_list_dbs()等为结果集分配的内存。 mysql_free_result(res); return 0; } // filename[in]: path + file name 要读取的文件名 // buffer[out]: store image data 存储文件的缓冲 int read_image(char *filename, char *buffer) { if (filename == NULL || buffer == NULL) return -1; FILE *fp = fopen(filename, "rb"); // if (fp == NULL) { printf("fopen failed\n"); return -2; } // file size fseek(fp, 0, SEEK_END); int length = ftell(fp); // file size fseek(fp, 0, SEEK_SET); int size = fread(buffer, 1, length, fp); if (size != length) { printf("fread failed: %d\n", size); return -3; } fclose(fp); return size; } // filename : 要写入的文件 // buffer : 读入的缓冲(图片数据已经存到该缓冲中) // length : 要读入的长度 int write_image(char *filename, char *buffer, int length) { if (filename == NULL || buffer == NULL || length <= 0) return -1; FILE *fp = fopen(filename, "wb+"); // if (fp == NULL) { printf("fopen failed\n"); return -2; } int size = fwrite(buffer, 1, length, fp);//将buffer的数据写入到文件中 if (size != length) { printf("fwrite failed: %d\n", size); return -3; } fclose(fp); return size; } //buffer的数据存入到mysql中 //buffer:要存取到数据库的buffer数据 //length:要存入的长度 int mysql_write(MYSQL *handle, char *buffer, int length) { if (handle == NULL || buffer == NULL || length <= 0) return -1; //MYSQL_STMT:该结构用于有预处理语句(带?的SQL,这里SQL是一个占位符,代表一个参数, //这个参数可能无法直接像varchar,int等可以表示出来,比如BLOG数据类型,需要使用MYSQL_BIND来绑定其参数)的SQL MYSQL_STMT *stmt = mysql_stmt_init(handle); // int ret = mysql_stmt_prepare(stmt, SQL_INSERT_IMG_USER, strlen(SQL_INSERT_IMG_USER)); if (ret) { printf("mysql_stmt_prepare : %s\n", mysql_error(handle)); return -2; } //MYSQL_BIND结构用于语句输入(发送给服务器的数据值)和输出(从服务器返回的结果值) MYSQL_BIND param = {0}; //语句输入(绑定输入参数) param.buffer_type = MYSQL_TYPE_LONG_BLOB;//指明了与语句参数捆绑的值类型 param.buffer = NULL;//指向存储语句参数数据值的缓冲的指针 param.is_null = 0;//如果数据值总是NOT NULL,设置is_null = (my_bool*) 0。 param.length = NULL; ret = mysql_stmt_bind_param(stmt, ¶m);//将参数和预处理语句结构进行绑定 if (ret) { printf("mysql_stmt_bind_param : %s\n", mysql_error(handle)); return -3; } //允许应用程序分段地(分块)将参数数据发送到服务器。可以多次调用该函数, //以便发送关于某一列的字符或二进制数据的不同部分,列必须是TEXT或BLOB数据类型之一。 ret = mysql_stmt_send_long_data(stmt, 0, buffer, length); if (ret) { printf("mysql_stmt_send_long_data : %s\n", mysql_error(handle)); return -4; } ret = mysql_stmt_execute(stmt);//执行与语句句柄相关的预处理查询。 if (ret) { printf("mysql_stmt_execute : %s\n", mysql_error(handle)); return -5; } ret = mysql_stmt_close(stmt);//释放预处理语句使用的内存。 if (ret) { printf("mysql_stmt_close : %s\n", mysql_error(handle)); return -6; } return ret; } //从数据库中将图片数据读入到buffer中 //buffer:存放数据的buffer //buffer的预分配长度 int mysql_read(MYSQL *handle, char *buffer, int length) { if (handle == NULL || buffer == NULL || length <= 0) return -1; MYSQL_STMT *stmt = mysql_stmt_init(handle); int ret = mysql_stmt_prepare(stmt, SQL_SELECT_IMG_USER, strlen(SQL_SELECT_IMG_USER)); if (ret) { printf("mysql_stmt_prepare : %s\n", mysql_error(handle)); return -2; } //result与mysql_stmt_bind_result()一起使用,用于绑定结果缓冲区,以便用于with mysql_stmt_fetch()以获取行。 MYSQL_BIND result = {0};//结果参数 result.buffer_type = MYSQL_TYPE_LONG_BLOB;//指明了你希望从结果缓冲收到的值类型。 unsigned long total_length = 0;//存放结果集的总长度(注意,这里是一行的总长度,后面mysql_stmt_fetch先得到一行的结果集,然后在对一行数据进行操作) 指向unsigned long变量的指针,该变量指明了存储在*buffer中数据的实际字节数。 result.length = &total_length; //将结果集中的列与数据缓冲和长度缓冲关联(绑定)起来。 ret = mysql_stmt_bind_result(stmt, &result); if (ret) { printf("mysql_stmt_bind_result : %s\n", mysql_error(handle)); return -3; } ret = mysql_stmt_execute(stmt);//执行与语句句柄相关的预处理查询。 if (ret) { printf("mysql_stmt_execute : %s\n", mysql_error(handle)); return -4; } //对于成功生成结果集的所有语句(SELECT、SHOW、DESCRIBE、EXPLAIN), //而且仅当你打算对客户端的全部结果集进行缓冲处理时, //必须调用mysql_stmt_store_result(),以便后续的mysql_stmt_fetch()调用能返回缓冲数据。 ret = mysql_stmt_store_result(stmt);//将结果存入到缓冲中 if (ret) { printf("mysql_stmt_store_result : %s\n", mysql_error(handle)); return -5; } //注意,如果如果有多个数据被查询出来,得到的是最后一张图片的数据 while (1) { ret = mysql_stmt_fetch(stmt);//返回结果集中的下一行。 // 出现错误或者数据读取完成时退出 if (ret != 0 && ret != MYSQL_DATA_TRUNCATED) break; int start = 0;//用于存放每一行距离缓冲的开始值 //循环得到一行图片的数据信息 while (start < (int)total_length) { //buffer和result.buffer公用一个空间, //下一行数据好像会覆盖上一次的数据, //也就是buffer最终得到的是最后一张图片的数据, //大家可以自己测试以下,比如一个名字有2行数据, //但是不是同一张图,看得到的是不是就是最后一行的数据 //由于每次start变量都在增加,因此指针的值也在增加, //result.buffer每次也在增加 //最终的buffer值会得到整个图片的值 result.buffer = buffer + start; //指明了每次可保存在缓冲区内的最大数据(这里设置为1字节,代表每次读取1个字节到buffer中) result.buffer_length = 1; //从当前结果集行获取1列,0-代表第一列,start是数据的偏移量, //将从该处开始检索数据,&result提供了应将数据置于其中的缓冲. mysql_stmt_fetch_column(stmt, &result, 0, start); start += result.buffer_length; } } mysql_stmt_close(stmt); return total_length;//返回最后一张图片的长度 } int main() { MYSQL mysql; if (NULL == mysql_init(&mysql)) { printf("mysql_init : %s\n", mysql_error(&mysql)); return -1; } if (!mysql_real_connect(&mysql, KING_DB_SERVER_IP, KING_DB_USERNAME, KING_DB_PASSWORD, KING_DB_DEFAULTDB, KING_DB_SERVER_PORT, NULL, 0)) { printf("mysql_real_connect : %s\n", mysql_error(&mysql)); goto Exit; } // mysql --> insert printf("case : mysql --> insert \n"); #if 1 if (mysql_real_query(&mysql, SQL_INSERT_TBL_USER, strlen(SQL_INSERT_TBL_USER))) { printf("mysql_real_query : %s\n", mysql_error(&mysql)); goto Exit; } #endif king_mysql_select(&mysql); // mysql --> delete #if 1 printf("case : mysql --> delete \n"); if (mysql_real_query(&mysql, SQL_DELETE_TBL_USER, strlen(SQL_DELETE_TBL_USER))) { printf("mysql_real_query : %s\n", mysql_error(&mysql)); goto Exit; } #endif king_mysql_select(&mysql); printf("case : mysql --> read image and write mysql\n"); char buffer[FILE_IMAGE_LENGTH] = {0}; int length = read_image("0voice.jpg", buffer);//要保证该图片存在 if (length < 0) goto Exit; mysql_write(&mysql, buffer, length); /// printf("case : mysql --> read mysql and write image\n"); memset(buffer, 0, FILE_IMAGE_LENGTH); length = mysql_read(&mysql, buffer, FILE_IMAGE_LENGTH); write_image("a.jpg", buffer, length); Exit: mysql_close(&mysql); return 0; }
代码运行
命令:gcc -o mysql mysql.c -I /usr/include/mysql/ -lmysqlclient
注意:要保证图片存在,否则无法对图片进行操作。
代码来源
腾讯课堂-零声学院king老师
工具准备
1 .Navicat或者workbench客户端操作工具
2. SSH连接工具,比如Xshell等(虚拟机环境)
3. mysql参考手册(使用C操作数据库的相关API的教程)
4. 另外window环境还建议搭建Samba服务。
PS
如果有需要工具或者其他错误问题的朋友,可以给我留言。
这篇关于linux C Mysql数据库增删改查(CURD)操作的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-07MySQL读写分离入门:轻松掌握数据库读写分离技术
- 2024-12-07MySQL读写分离入门教程
- 2024-12-07MySQL分库分表入门详解
- 2024-12-07MySQL分库分表入门指南
- 2024-12-07MySQL慢查询入门:快速掌握性能优化技巧
- 2024-12-07MySQL入门:新手必读的简单教程
- 2024-12-07MySQL入门:从零开始学习MySQL数据库
- 2024-12-07MySQL索引入门:新手快速掌握MySQL索引技巧
- 2024-12-06BinLog学习:MySQL数据库BinLog入门教程
- 2024-12-06Binlog学习:MySQL数据库的日志管理入门教程