mysql数据库 C代码和workbench远程连接
下载mysql
sudo apt-get install mysql-server
sudo mysql -u root -p
过程中没有让我设置初始密码,这里直接回车进入。
修改密码:
your_new_password应该替换为您想要设置的新密码。
ALTER USER 'root'@'localhost' IDENTIFIED BY 'your_new_password';
可以通过以下命令验证密码是否已更改:
SELECT User, Host, authentication_string FROM mysql.user WHERE User='root';


远程连接mysql
10061报错
在Hostname输入本机的公网ip地址(ifconfig获得)
设置数据库密码
点击Test Connection,报错10061。

说明数据库服务器返回给workbench了10061的错误,那么服务器肯定工作了。
打开数据库的配置文件
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
127.0.0.1是回环地址 机器内部使用的地址 外界访问不到

改成0.0.0.0,表示任意地址

重启mysql服务
sudo /etc/init.d/mysql restart
not allowed报错
重新尝试Test Connection,报错:

说明数据库服务器限制root的远程登录
查看当前用户的 Host 授权范围,输出显示仅允许本地登录:

不建议修改root,最高权限,企业运营过程中root非常重要。
创建一个新用户
create user 'admin'@'%' identified by 'your_password';
查看用户
select User, Host From user;

%表示任意地址,即任何地址都可以用admin用户登录
ssl报错

MySQL命令查看SSl
SHOW VARIABLES LIKE "%SSL%"

说明SSL已经启用。
修改配置文件跳过SSL:在尾行添加`skip_ssl`,重启mysql服务
查看ssl,已经关闭了:

外部组件异常报错

这是因为用了5. 版本的workbench,而我通过`sudo apt-get install mysql-server`下载的版本为8.0,加密方式为caching_sha2_password,5. 版本的客户端还不支持。因此需要修改 mysql 用户密码的加密方式。
查看加密方式
sudo mysql -u root -p
USE mysql;
select user, host, plugin, authentication_string from user;

ALTER USER 'admin'@'%' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER; #设置密码永不过期
ALTER USER 'admin'@'%' IDENTIFIED WITH mysql_native_password BY 'password'; #修改密码加密方式
FLUSH PRIVILEGES; #更新
Connection Warining

终于发现是版本问题。去下了一个新版本的workbench,成功连接了。
使用workbench远程操作数据库
选择sql语句,点击小闪电执行语句

报错:
![]()
admin没有权限操作数据库mysql,使用root用户的权限赋予admin用户select权限
grant select on mysql.* to 'admin'@'%';
然后就可以执行use mysql和select相关操作,但还不能create。
赋予其所有权限,相当与root的权限:
grant all privileges on *.* to 'admin'@'%';
创建数据库YU_DB,并在其中创建表TBL_USER
CREATE DATABASE YU_DB;
SHOW DATABASES;
USE YU_DB;
CREATE TABLE TBL_USER(
U_ID INT PRIMARY KEY AUTO_INCREMENT,
U_NAME VARCHAR(32),
U_GENGDER VARCHAR(8)
);
SHOW TABLES;
使用C代码远程操作数据库
插入数据
c代码如下
#include <mysql.h>
#include <stdio.h>
#include <string.h>
#define DB_SERVER_PORT 3306
#define DB_SERVER_IP "192.168.189.128"
#define DB_USERNAME "admin"
#define DB_PASSWORD "197523@cyr"
#define DB_NAME "YU_DB"
#define SQL_INSERT_TBL_USER "INSERT TBL_USER(U_NAME, U_GENGDER) VALUES('yu', 'woman');"
int main(){
MYSQL mysql;
// 初始化数据库
if(NULL == mysql_init(&mysql)){
printf("mysql_init : %s\n",mysql_error(&mysql));
return -1;
}
//连接数据库,非0为成功
if(!mysql_real_connect(&mysql,DB_SERVER_IP,DB_USERNAME,DB_PASSWORD,DB_NAME,DB_SERVER_PORT, NULL,0)){
printf("mysql_real_connect : %s\n",mysql_error(&mysql));
}
//传递SQL语句,0为成功
if(mysql_real_query(&mysql,SQL_INSERT_TBL_USER,strlen(SQL_INSERT_TBL_USER))){
printf("mysql_real_query : %s\n",mysql_error(&mysql));
}
//关闭数据库
mysql_close(&mysql);
return 0;
}
在ns服务器上(node server)上安装mysql的客户端操作库
sudo apt-get install libmysqlclient-dev
指定mysql的系统头文件、mysql的库,进行编译运行
gcc -o mysql mysql.c -I /usr/include/mysql/ -l mysqlclient
./mysql
回到workbench,运行
SELECT * FROM TBL_USER;
成功插入数据

查询数据
int yu_mysql_select(MYSQL *handle){
//传递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;
}
//存储结果
MYSQL_RES *res = mysql_store_result(handle);
if(res == NULL){
printf("mysql_real_query: %s\n",mysql_error(handle));
return -2;
}
//确定结果的行列数
int rows = mysql_num_rows(res);
printf("row: %d\n", rows);
int fields = mysql_num_fields(res);
printf("fields: %d\n",fields);
//抓取数据
MYSQL_ROW row;
while((row = mysql_fetch_row(res))){
int i = 0;
for(i = 0;i < fields;i++){
printf("%s\t", row[i]);
}
printf("\n");
}
}
删除数据
workbench实现
DELETE FROM TBL_USER WHERE U_NAME='yu';
U_NAME非主键,这样删除不安全。在安全模式下命令会被拒绝
关闭安全模式,执行完命令后再开启
SET SQL_SAFE_UPDATES=0;
DELETE FROM TBL_USER WHERE U_NAME='yu';
SET SQL_SAFE_UPDATES=1;
容易出错.
存储过程
CREATE PROCEDURE PROC_DELETE_USER(IN UNAME VARCHAR(32))
BEGIN
SET SQL_SAFE_UPDATES=0;
DELETE FROM TBL_USER WHERE U_NAME=UNANE;
SET SQL_SAFE_UPDATES=1;
END

这里报错,需要结束标识符。正确写法:
DELIMITER %%
CREATE PROCEDURE PROC_DELETE_USER(IN UNAME VARCHAR(32))
BEGIN
SET SQL_SAFE_UPDATES=0;
DELETE FROM TBL_USER WHERE U_NAME=UNANE;
SET SQL_SAFE_UPDATES=1;
END %%
%%可以替换为其他符号
调用存储过程
CALL PROC_DELETE_USER('qiuxiang');
删除存储过程
DROP PROCEDURE PROC_DELETE_USER;
代码实现
#define SQL_DELETE_TBL_USER "CALL PROC_DELETE_USER('darren')"
……
if(mysql_real_query(&mysql,SQL_DELETE_TBL_USER,strlen(SQL_DELETE_TBL_USER))){
printf("mysql_real_query : %s\n",mysql_error(&mysql));
}
……
图片插入数据库
- 准备好一张图片,读入内存
- 把图片数据存入数据库
- 如何把图片从数据库中读出来
- 写入磁盘
#include <mysql.h>
#include <stdio.h>
#include <string.h>
#define DB_SERVER_PORT 3306
#define DB_SERVER_IP "192.168.189.128"
#define DB_USERNAME "admin"
#define DB_PASSWORD "197523@cyr"
#define DB_NAME "YU_DB"
#define SQL_INSERT_TBL_USER "INSERT TBL_USER(U_NAME, U_GENDER) VALUES('darren', 'man');"
#define SQL_SELECT_TBL_USER "SELECT * FROM TBL_USER;"
#define SQL_DELETE_TBL_USER "CALL PROC_DELETE_USER('darren')"
#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 (500*1024)
int yu_mysql_select(MYSQL *handle){
//传递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;
}
//存储结果
MYSQL_RES *res = mysql_store_result(handle);
if(res == NULL){
printf("mysql_real_query: %s\n",mysql_error(handle));
return -2;
}
//确定结果的行列数
int rows = mysql_num_rows(res);
printf("row: %d\n", rows);
int fields = mysql_num_fields(res);
printf("fields: %d\n",fields);
//抓取数据
MYSQL_ROW row;
while((row = mysql_fetch_row(res))){
int i = 0;
for(i = 0;i < fields;i++){
printf("%s\t", row[i]);
}
printf("\n");
}
}
//从内存读取图片的二进制数据
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;
}
//检测文件大小
fseek(fp, 0, SEEK_END);//文件指针置末尾 偏移量0表示在末尾
int length = ftell(fp);
fseek(fp, 0, SEEK_SET);//文件指针置开头 偏移量0表示在开头
//读取length个数据块,每个数据块大小1,返回读到的数据块个数
int size = fread(buffer, 1, length, fp);
if(size!=length){
printf("fread failed: %d %d\n", size, length);
return -2;
}
fclose(fp);
return size;
}
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");
}
int size = fwrite(buffer, 1, length, fp);
if(size != length){
printf("fwrite failed: %d\n", size);
return -3;
}
fclose(fp);
return size;
}
int mysql_write(MYSQL* handle, char* buffer, int length){
if(handle == NULL || buffer == NULL || length <= 0) return -1;
//准备好stmt
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;
}
//准备好stmt的绑定参数
MYSQL_BIND param = {0};
param.buffer_type = MYSQL_TYPE_LONG_BLOB;
param.buffer = NULL;
param.is_null = 0;
param.length = NULL;
//绑定stmt与param
ret = mysql_stmt_bind_param(stmt, ¶m);
if(ret){
printf("mysql_stmt_bind_param : %s\n", mysql_error(handle));
return -3;
}
//分片发送数据给数据库
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_execute : %s\n", mysql_error(handle));
return -6;
}
return ret;
}
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;
}
MYSQL_BIND result = {0};
result.buffer_type = MYSQL_TYPE_LONG_BLOB;
unsigned long total_length = 0;
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;
}
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){
result.buffer = buffer + start;
result.buffer_length = 1;
mysql_stmt_fetch_column(stmt,&result, 0, start);
start += result.buffer_length;
}
}
ret = mysql_stmt_close(stmt);
if(ret){
printf("mysql_stmt_execute : %s\n", mysql_error(handle));
return -6;
}
return total_length;
}
int main(){
MYSQL mysql;
// 初始化数据库
if(NULL == mysql_init(&mysql)){
printf("mysql_init : %s\n",mysql_error(&mysql));
return -1;
}
//连接数据库,非0为成功
if(!mysql_real_connect(&mysql,DB_SERVER_IP,DB_USERNAME,DB_PASSWORD,DB_NAME,DB_SERVER_PORT, NULL,0)){
printf("mysql_real_connect : %s\n",mysql_error(&mysql));
return -1;
}
//传递SQL语句,0为成功
#if 1
printf("case: mysql --> insert\n");
//插入
if(mysql_real_query(&mysql,SQL_INSERT_TBL_USER,strlen(SQL_INSERT_TBL_USER))){
printf("mysql_real_query : %s\n",mysql_error(&mysql));
}
#endif
//查询
yu_mysql_select(&mysql);
printf("case: mysql --> delete\n");
#if 1
//删除
if(mysql_real_query(&mysql,SQL_DELETE_TBL_USER,strlen(SQL_DELETE_TBL_USER))){
printf("mysql_real_query : %s\n",mysql_error(&mysql));
}
yu_mysql_select(&mysql);
#endif
printf("case: mysql --> read image and write mysql\n");
char buffer[FILE_IMAGE_LENGTH];
int length = read_image("image.png", 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;
}
思考题:实现数据库的连接池
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)