MySQL数据库的开发

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地址 配密码

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇