CentOS7安装MySQL + 创建表
本地版的MySQL用着用着就挂了,在星佬的帮助下整了个docker版的数据库。
直接把他的笔记贴到文章的最后面吧。
实话实说,有点折腾
先按照这个pdf把本地版的MySQL装好
然后能在命令行启动mysql了
centos yum安装mysql出现Public key for mysql-community-server-5.7.37-1.el7.x86_64.rpm is not installed?
https://blog.csdn.net/searlas/article/details/123393829
找不到mysql.h?
yum search mysql
找到 Development header files
,把有这个的全装上
如
yum install mysql-community-devel.x86_64
然后用 find / -name "mysql"
找含有mysql的文件夹目录有哪些,再一个个打开看
找到含有 mysql.h 的文件目录是 /usr/include/mysql
含有 mysql 相关库的目录是 /usr/lib64/mysql
makefile 这样写
# mysql头文件存放的目录。
MYSQLINCL = -I/usr/include/mysql
# mysql库文件存放的目录。
MYSQLLIB = -L/usr/lib64/mysql
# 需要链接的mysql库。
MYSQLLIBS = -lmysqlclient
CFLAGS=-g -Wno-write-strings
all:testmysql
testmysql: testmysql.cpp _mysql.h _mysql.cpp
g++ $(CFLAGS) -o testmysql testmysql.cpp $(MYSQLINCL) $(MYSQLLIB) $(MYSQLLIBS) _mysql.cpp -lm -lc
clean:
rm -rf testmysql
再使用C++测试下
#include "_mysql.h" // 开发框架操作MySQL的头文件。
int main(int argc,char *argv[])
{
connection conn; // 数据库连接类。
// 登录数据库,返回值:0-成功;其它是失败,存放了MySQL的错误代码。
// 失败代码在conn.m_cda.rc中,失败描述在conn.m_cda.message中。
if (conn.connecttodb("127.0.0.1,root,123456,mysql,3306","utf8")!=0)
{
printf("connect database failed.\n%s\n",conn.m_cda.message); return -1;
}
sqlstatement stmt(&conn); // 操作SQL语句的对象。
// 准备创建表的SQL语句。
// 超女表girls,超女编号id,超女姓名name,体重weight,报名时间btime,超女说明memo,超女图片pic。
stmt.prepare("create table girls(id bigint(10),\
name varchar(30),\
weight decimal(8,2),\
btime datetime,\
memo longtext,\
pic longblob,\
primary key (id))");
/*
1、int prepare(const char *fmt,...),SQL语句可以多行书写。
2、SQL语句最后的分号可有可无,建议不要写(兼容性考虑)。
3、SQL语句中不能有说明文字。
4、可以不用判断stmt.prepare()的返回值,stmt.execute()时再判断。
*/
// 执行SQL语句,一定要判断返回值,0-成功,其它-失败。
// 失败代码在stmt.m_cda.rc中,失败描述在stmt.m_cda.message中。
if (stmt.execute()!=0)
{
printf("stmt.execute() failed.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message); return -1;
}
printf("create table girls ok.\n");
return 0;
}
/*
-- 超女基本信息表。
create table girls(id bigint(10), -- 超女编号。
name varchar(30), -- 超女姓名。
weight decimal(8,2), -- 超女体重。
btime datetime, -- 报名时间。
memo longtext, -- 备注。
pic longblob, -- 照片。
primary key (id));
*/
成功操作数据库
增删查改数据
流程是:连接、执行、提交事务
这里有两点值得注意,一是可变参数里面的%
不能直接写,要转义,用%%
代替;二是_1
后面可以添上+1
这样的数字。
增加
增加的demo如下:
#include <unistd.h>
#include "_mysql.h" // 开发框架操作MySQL的头文件。
int main(int argc,char *argv[])
{
connection conn; // 数据库连接类。
// 登录数据库,返回值:0-成功;其它是失败,存放了MySQL的错误代码。
// 失败代码在conn.m_cda.rc中,失败描述在conn.m_cda.message中。
if (conn.connecttodb("127.0.0.1,root,wsm24458,qixiang,3306","utf8")!=0)
{
printf("connect database failed.\n%s\n",conn.m_cda.message); return -1;
}
// 定义用于超女信息的结构,与表中的字段对应。
struct st_girls
{
long id; // 超女编号
char name[31]; // 超女姓名
double weight; // 超女体重
char btime[20]; // 报名时间
} stgirls;
sqlstatement stmt(&conn); // 操作SQL语句的对象。
// 准备插入表的SQL语句。
stmt.prepare("\
insert into girls(id,name,weight,btime) values(:1+1,:2,:3+45.35,str_to_date(:4,'%%Y-%%m-%%d %%H:%%i:%%s'))");
//insert into girls(id,name,weight,btime) values(?+1,?,?+45.35,to_date(?,'yyyy-mm-dd hh24:mi:ss'))");
/*
注意事项:
1、参数的序号从1开始,连续、递增,参数也可以用问号表示,但是,问号的兼容性不好,不建议;
2、SQL语句中的右值才能作为参数,表名、字段名、关键字、函数名等都不能作为参数;
3、参数可以参与运算或用于函数的参数;
4、如果SQL语句的主体没有改变,只需要prepare()一次就可以了;
5、SQL语句中的每个参数,必须调用bindin()绑定变量的地址;
6、如果SQL语句的主体已改变,prepare()后,需重新用bindin()绑定变量;
7、prepare()方法有返回值,一般不检查,如果SQL语句有问题,调用execute()方法时能发现;
8、bindin()方法的返回值固定为0,不用判断返回值;
9、prepare()和bindin()之后,每调用一次execute(),就执行一次SQL语句,SQL语句的数据来自被绑定变量的值。
*/
stmt.bindin(1,&stgirls.id);
stmt.bindin(2, stgirls.name,30);
stmt.bindin(3,&stgirls.weight);
stmt.bindin(4, stgirls.btime,19);
// 模拟超女数据,向表中插入5条测试数据。
for (int ii=0;ii<5;ii++)
{
memset(&stgirls,0,sizeof(struct st_girls)); // 结构体变量初始化。
// 为结构体变量的成员赋值。
stgirls.id=ii; // 超女编号。
sprintf(stgirls.name,"西施%05dgirl",ii+1); // 超女姓名。
stgirls.weight=ii; // 超女体重。
sprintf(stgirls.btime,"2021-08-25 10:33:%02d",ii); // 报名时间。
// 执行SQL语句,一定要判断返回值,0-成功,其它-失败。
// 失败代码在stmt.m_cda.rc中,失败描述在stmt.m_cda.message中。
if (stmt.execute()!=0)
{
printf("stmt.execute() failed.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message); return -1;
}
printf("成功插入了%ld条记录。\n",stmt.m_cda.rpc); // stmt.m_cda.rpc是本次执行SQL影响的记录数。
}
printf("insert table girls ok.\n");
conn.commit(); // 提交数据库事务。
return 0;
}
修改
把语句改成修改的即可。
// 准备修改表的SQL语句。
stmt.prepare("\
update girls set name=:1,weight=:2,btime=str_to_date(:3,'%%Y-%%m-%%d %%H:%%i:%%s') where id=:4");
查询
相比于前面的有两点不同:【1】使用了bindout输出到屏幕【2】查询不需要提交事务,没有用commit
stmt.prepare("\
select id,name,weight,date_format(btime,'%%Y-%%m-%%d %%H:%%i:%%s') from girls where id>=:1 and id<=:2");
// 为SQL语句绑定输入变量的地址,bindin方法不需要判断返回值。
stmt.bindin(1,&iminid);
stmt.bindin(2,&imaxid);
// 为SQL语句绑定输出变量的地址,bindout方法不需要判断返回值。
stmt.bindout(1,&stgirls.id);
stmt.bindout(2, stgirls.name,30);
stmt.bindout(3,&stgirls.weight);
stmt.bindout(4, stgirls.btime,19);
删除
改下SQL语句,再commit下
stmt.prepare("delete from girls where id>=:1 and id<=:2");
二进制大对象的存取
MySQL里面有两种大对象:text和blob。对数据库有修改的就commit下事务。
存到数据库里面就是用blob,取出来就是text。
存入数据库:
// 准备修改表的SQL语句。
stmt.prepare("update girls set pic=:1 where id=:2");
stmt.bindinlob(1, stgirls.pic,&stgirls.picsize);
stmt.bindin(2,&stgirls.id);
// 把图片的内容加载到stgirls.pic中。
if (ii==1) stgirls.picsize=filetobuf("1.jpg",stgirls.pic);
if (ii==2) stgirls.picsize=filetobuf("2.jpg",stgirls.pic);
conn.commit(); // 提交数据库事务。
从数据库里取出来:
// 准备查询表的SQL语句。
stmt.prepare("select id,pic from girls where id in (1,2)");
stmt.bindout(1,&stgirls.id);
stmt.bindoutlob(2, stgirls.pic,100000,&stgirls.picsize);
// 把内容写入文件。
buftofile(filename,stgirls.pic,stgirls.picsize);
数据库开发要注意的事项
主要是两个。一是多进程不能共有一个连接;二是C语言不能表示空的整数和浮点数。
针对问题一,fork()
之后再连接数据库。
针对问题二,用字符串代替数字,只要能存下就行了。
入库
站点参数
程序代码/project/idc/c/obtcodetodb.cpp
配置文件地址是/project/idc/ini/stcode.ini
里面的内容长这样
省 站号 站名 纬度 经度 海拔高度
安徽,58015,砀山,34.27,116.2,44.2
安徽,58102,亳州,33.47,115.44,39.1
先用PowerDesigner设计表。
drop table if exists T_ZHOBTCODE;
/*==============================================================*/
/* Table: T_ZHOBTCODE */
/*==============================================================*/
create table T_ZHOBTCODE
(
obtid varchar(10) not null comment '站点代码',
cityname varchar(30) not null comment '城市名称',
provname varchar(30) not null comment '省名称',
lat int not null comment '纬度,单位:0.01度。',
lon int not null comment '经度,单位:0.01度。',
height int comment '海拔高度,单位:0.1米。',
upttime timestamp not null comment '更新时间,数据被插入或更新的时间',
keyid int not null comment '记录编号,自动增长列。',
primary key (obtid),
key AK_ZHOBTCODE_KEYID (keyid)
);
alter table T_ZHOBTCODE comment '这是一个参数表,存放了全国的站点参数,约800条数据,本表的数据极少更变。
应用程序对本表有insert和u';
用这个结构体存放数据
// 全国气象站点参数结构体。
struct st_stcode
{
char provname[31]; // 省
char obtid[11]; // 站号
char cityname[31]; // 站名
char lat[11]; // 纬度
char lon[11]; // 经度
char height[11]; // 海拔高度
};
打开配置文件,将数据读入结构体数组,再一个个结构体往MySQL里面写入。如果没有就写入;如果写入就更新。
【改了两个小时的bug,原因是我的表在qixiang库里面,运行程序写的mysql库,而mysql库里刚好有这个表,,】
站点数据
和站点参数的流程也差不太多,思路是一样的。无非打开文件然后读取数据。
/*==============================================================*/
/* Table: T_ZHOBTMIND */
/*==============================================================*/
create table T_ZHOBTMIND
(
obtid varchar(10) not null comment '站点代码',
ddatetime datetime not null comment '数据时间,精准到分钟',
t int comment '温度,单位:0.1摄氏度',
p int comment '气压,单位:0.1百帕',
u int comment '相对湿度,0-100之间',
wd int comment '风向,0-360之间的值',
wf int comment '风速,单位0.1m/s',
r int comment '降雨量:0.1mm',
vis int comment '能见度:0.1米',
upttime timestamp not null comment '更新时间',
keyid bigint not null auto_increment comment '记录编号,自动增长列',
primary key (obtid, ddatetime),
key AK_ZHOBTMIND_KEYID (keyid)
);
alter table T_ZHOBTMIND comment '本表存放了全国站点分钟数据,站点数约840个,数据周期为1分钟
应用程序对本表只有insert操作,没有up';
/*==============================================================*/
/* Index: IDX_ZHOBTMIND_1 */
/*==============================================================*/
create unique index IDX_ZHOBTMIND_1 on T_ZHOBTMIND
(
ddatetime,
obtid
);
/*==============================================================*/
/* Index: IDX_ZHOBTMIND_2 */
/*==============================================================*/
create index IDX_ZHOBTMIND_2 on T_ZHOBTMIND
(
ddatetime
);
/*==============================================================*/
/* Index: IDX_ZHOBTMIND_3 */
/*==============================================================*/
create index IDX_ZHOBTMIND_3 on T_ZHOBTMIND
(
obtid
);
alter table T_ZHOBTMIND add constraint FK_Reference_2 foreign key (obtid)
references T_ZHOBTCODE (obtid) on delete restrict on update restrict;
1、本人是在aliyun部署(centos环境)
本地挂载盘: /data/mymysql/
需要四个文件夹
mkdir conf
touch my.cnf
mkdir data
mkdir log
mkdir mysql-files
my.cnf配置信息
# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# The MySQL Server configuration file.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
secure-file-priv= NULL
default-time-zone = '+8:00'
#最大链接数
max_connections=1024
#是否对sql语句大小写敏感,1表示不敏感
lower_case_table_names=1
log_bin_trust_function_creators=1
#启用log-bin
log-bin=mysql-bin
#设置日志格式
binlog_format=mixed
#设置binlog清理时间
expire_logs_days=7
# 数据表默认时区
default-time-zone='+08:00'
# Custom config should go here
!includedir /etc/mysql/conf.d/
2、拉取镜像latest(mysql8.0.32)
docker pull mysql
3、执行命令
docker run -p 3306:3306 --name mysql -v /docker/mysql/log:/var/log/mysql -v /docker/mysql/data:/var/lib/mysql -v /docker/mysql/conf:/etc/mysql/conf.d -v /docker/mysql/mysql-files:/var/lib/mysql-files -e MYSQL_ROOT_PASSWORD=root -d mysql:latest
4、进入
docker exec -it mysql bash
先修改下mysql root用户密码
use mysql;
ALTER USER 'root'@'localhost' IDENTIFIED BY '';·#此处是修改本地登录的密码
ALTER USER 'root'@'%' IDENTIFIED BY '';·#此处是修改远程登录的密码
select host,user,authentication_string from user;#此处查看用户表
刷新权限
flush privileges;
实现远程登录
alter user 'root'@'%' identified with mysql_native_password by 'root';
改socket地址 配密码