Back

Mysql数据库

1 MySQL基础知识

瑞典MySQL AB公司开发,由SUN收购,而后SUN被甲骨文并购,目前属于Oracle公司。

MySQL是一种关联数据库管理系统 由于其体积小、速度快、总体拥有成本低、MySQL软件采用了双授权政策,分为社区版和企业版。

1.1 MySQL版本及下载

MySQL数据库版本相对比较繁杂。常见的有:Community社区版、Enterprise企业版。

MySQL Community Server 版是开源免费的,这也是我们通常用的MySQL的版本。可以满足绝大多数用户需求。

MySQL Enterprise Edition 企业版收费的,官方指出提供30天免费试用期。可进一步划分为MySQL标准版、MySQL企业版、MySQL集群版。官方提供付费服务。

其中Community Server 可以直接从mysql 的官网下载。但Enterprice Edition只能从Oracle edelivery上下载,而Edelivery有时会屏蔽中国IP。

MySQL各版本区别参见:

http://www.admin10000.com/Document/62.html

下载mysql时注意区分版本细节及所应用的系统平台:linux(32/64)win(32/64)

举例:

win版本:

mysql-installer-community-8.0.26.0.msi版本

​ GA 是指软件的通用版本,一般指正式发布的版本 (Generally Available (GA) Release)

​ mysql-essential-5.1.60-win32.msi精简版,如果只需要mysql服务,就选择此版本。

​ mysql-5.1.60-win32.msi 是完 是整版,包含安装程序和配置向导,有MySQL文档。

mysql-noinstall-5.1.60-win32.zip 是非安装的zip压缩包,没有自动安装程序和配置向导,无安装向导

​ mysql-5.1.60.zip 是用于windows的Mysql源码压缩包

linux版本

​ 在http://www.mysql.com/downloads/网站上下载不了

​ 在 www.oracle.com/downloads 找mysql 注册用户, 选择操作系统平台和mysql版本 进行下载

官方文档上有关MySQL安装,介绍了3种类型及其对应安装方式来安装MySQL数据库:

  Linux supports a number of different solutions for installing MySQL. The recommended method is to use one of the distributions from Oracle. If you choose this method, there are three options available:

(1) Installing from a generic binary package in .tar.gz format. See Section 2.2,“Installing MySQL from Generic Binaries on Unix/Linux”for more information.

(2) Extracting and compiling MySQL from a source distribution. For detailed instructions, see Section 2.9, “Installing MySQL from Source”.

(3) Installing using a pre-compiled RPM package. For more information on using the RPM solution, see Section 2.5.1,“Installing MySQL from RPM Packages on Linux”

我们选用较简单的RPM 包来安装。

1.2 下载安装包

Community Server 下载地址:https://dev.mysql.com/downloads/mysql/

MySQL Community Server. mysql社区版,开源、免费

MySQL Enterprise Edition. mysql企业版,非免费

MySQL Cluster. mysql集群版,开源、免费

2 MySQL服务器安装和启动

2.1 查询服务器上已经安装的mysql

​ 在终端提示符输入:rpm -aq | grep mysql 命令。查询结果如下显示:

qt-mysql-4.6.2-25.el6.x86_64

mysql-connector-odbc-5.1.5r1144-7.el6.x86_64

mysql-bench-5.1.66-2.el6_3.x86_64

mysql-devel-5.1.66-2.el6_3.x86_64

libdbi-dbd-mysql-0.8.3-5.1.el6.x86_64

mysql-test-5.1.66-2.el6_3.x86_64

mysql-libs-5.1.66-2.el6_3.x86_64

mysql-5.1.66-2.el6_3.x86_64

mysql-connector-java-5.1.17-6.el6.noarch

mysql-server-5.1.66-2.el6_3.x86_64

​ 注:各机器有可能不相同,软件列表视实际情况。

2.2 卸载旧的版本

rpm -e 软件包名 –nodeps –allmatches (不理会依赖关系,删除所有上一步查出来的相同的mysql)

[root@localhost home]# rpm -e mysql-connector-odbc-3.51.26r1127-1.el5 --nodeps --allmatches
    
[root@localhost home]# rpm -e libdbi-dbd-mysql-0.8.1a-1.2.2 --nodeps --allmatches
    
[root@localhost home]# rpm -e mysql-server-5.0.77-3.el5 --nodeps --allmatches
    
[root@localhost home]# rpm -aq | grep mysql
    
[root@localhost home]# 

将老版本的几个文件手动删除

rm -f /etc/my.cnf
    
rm -rf /var/lib/mysql
    
rm -rf /var/share/mysql
    
rm -rf /usr/bin/mysql*

2.3 安装

解压.zip安装包

unzip V46610-01-MySQL Database 5.6.20 RPM for Oracle Linux RHEL 6 x86 (64bit).zip

得到如下软件包

MySQL-client-advanced-5.6.20-1.el6.x86_64.rpm
  
MySQL-devil-advanced-5.6.20-1.el6.x86_64.rpm
    
MySQL-server-advanced-5.6.20-1.el6.x86_64.rpm
    
MySQL-embedded-advanced-5.6.20-1.el6.x86_64.rpm
  
MySQL-shared-advanced-5.6.20-1.el6.x86_64.rpm
    
MySQL-shared-compal-advanced-5.6.20-1.el6.x86_64.rpm
   
MySQL-test-advanced-5.6.20-1.el6.x86_64.rpm
    
README.txt

2.3.1 安装服务器

rpm -ivh MySQL-server-advanced-5.6.****-1.el6.x86_64.rpm
    
A RANDOM PASSWORD HAS BEEN SET FOR THE MySQL root USER !
    
You will find that password in '/root/.mysql_secret'.
    
You must change that password on your first connect,
    
no other statement but 'SET PASSWORD' will be accepted.
    
See the manual for the semantics of the 'password expired' flag.
    
Also, the account for the anonymous user has been removed.
    
In addition, you can run:
    
    /usr/bin/mysql_secure_installation
    
which will also give you the option of removing the test database.
    
This is strongly recommended for production servers.
    
See the manual for more instructions.
    
Please report any problems at http://bugs.mysql.com/
    
The latest information about MySQL is available on the web at
    
http://www.mysql.com
    
Support MySQL by buying support/licenses at http://shop.mysql.com
    
New default config file was created as /usr/my.cnf and
    
will be used by default by the server when you start it.
    
You may edit this file to change server settings

2.3.2 安装客户端:

rpm -ivh MySQL-client-advanced-5.6.****-1.el6.x86_64.rpm

说明:不安装mysql-client是不能使用mysql工具登陆到mysql数据库

​ 其他软件包选择性安装: rpm -ivh MySQL-devel-advanced-5.6.20-1.el6.x86_64.rpm

2.4 查看mysql服务器是否已经启动

# 查看状态
systemctl status mysqld 
# 启动mysql
systemctl start mysqld 
# 关闭mysql
systemctl stop mysqld 
# 重新启动mysql
systemctl restart mysqld 
# 开机启动mysql
systemctl enable mysqld 
# 关闭开机启动mysql
systemctl disable mysqld
# 另外一种操作方式
service mysqld status 

2.5 登录Mysql

oracle收购Mysql后, 新版的mysql刚安装完mysql后不能直接输入mysql登录数据库, 而是设置了默认free password密码, 默认密码放在了/root/.mysql_secret文件中, 登陆后需要修改密码。

1.查看文件寻找密码

cat /root/.mysql_secret

2.以root用户身份登陆MySQL

服务启动和关闭:

service mysql start

service mysql stop

ps -u mysql #可以查看mysql用户(安装MySQL时,系统自动创建该用户)的进程

PID TTY     TIME CMD

7586 ?         00:00:50 mysqld     守护进程

登陆服务器

mysql -uroot –p 密码

输入从.mysql_secret中读到的密码登录。

如果登录期间发生异常,无法登陆:

使用root将mysql的后台进程kill -9 PID

3.修改密码

mysql> set password=password('123456'); 将密码设置为:123456

密码修改成后,再次登录使用:

$mysql -uroot -p123456 即可。

4.查看数据库

mysql> show databases; clip_image002.jpg

5.远程root登录mysql

5.1Mysql8.0创建用户和授权

mysql8.0需要先创建用户和设置密码,然后才能授权.

#先创建一个用户
create user 'tone'@'%' identified by '123123';
 
#再进行授权
grant all privileges on *.* to 'tone'@'%' with grant option;

5.2MySQL8.0 的远程链接

MySQL 安装完成后只支持 localhost 访问,我们必须设置一下才可以远程访问,另外还有一些 MySQL 8.0 连接时的一些问题.

5.2.1登录MySQL
mysql -u root -p
#然后输入您的密码
5.2.2选择 mysql 数据库
use mysql;
--因为 mysql 数据库中存储了用户信息的 user 表。   
5.2.3在 mysql 数据库的 user 表中查看当前 root 用户的相关信息
select host, user, authentication_string, plugin from user; 
--执行完上面的命令后会显示一个表格
--查看表格中 root 用户的 host,默认应该显示的 localhost,只支持本地访问,不允许远程访问。
5.2.4授权 root 用户的所有权限并设置远程访问
GRANT ALL ON *.* TO 'root'@'%';
GRANT ALL ON 表示所有权限,% 表示通配所有 host,可以访问远程。
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '你自己的密码';
5.2.5刷新权限
--所有操作后,应执行    
flush privileges;

5.2.6查看 root 用户的 host

use mysql;
select host, user, authentication_string, plugin from user;
--会发现 root 用户的 host 已经变成 %,说明我们的修改已经成功,可以远程访问了。

mysql8远程连接.jpg

5.3访问数据库

    --输入访问的 host 和密码,报 2059 错误,这是因为 MySql8.0 版本 和 5.7 的加密规则不一样,而现在的可视化工具只支持旧的加密方式。
    
    --出现这个原因是mysql8 之前的版本中加密规则是mysql_native_password,而在mysql8之后,加密规则是caching_sha2_password.
    --解决问题方法有两种,一种是升级navicat驱动,一种是把mysql用户登录密码加密规则还原成mysql_native_password.
    
    --这里采用第二种方式 :
        
        --修改加密规则:
        ALTER USER 'root'@'%' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER; 
        password 为你当前密码。
    
        --更新 root 用户密码:
        ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'password'; 
        password 为你新设置的密码。
    
        --刷新权限:
        FLUSH PRIVILEGES; 
        --OK,设置完成,再次使用 Navicat 连接数据库

6. 数据库的CURD

对数据库进行增(Create)、改(Update) 、查(Retrieve) 、删(Delete)操作。

6.1查看数据库

  • 显示所有数据库

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| itcast             |
| itcast1            |
| itcast2            |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
7 rows in set (0.01 sec)
  • 显示创建数据库的语句信息
mysql> show create database itcast;
+----------+-----------------------------------------------------------------+
| Database | Create Database                                              |
+----------+-----------------------------------------------------------------+
| itcast   | CREATE DATABASE `itcast` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+----------+-----------------------------------------------------------------+
1 row in set (0.00 sec)
  
/* `itcast` 两端是反单引号, esc下的键, 使用``包含数据库的名字是区分大小写的 */
  • 使用数据库
/* 我们以root用户登录, 用户下有很多数据库, 需要指定, 当前使用哪一个数据库, 操作的就是那个数据库中的数据 */
mysql> use itcast1;
Database changed
mysql> use itcast2;
Database changed

6.2创建数据库

-- IF NOT EXISTS 表示只有数据库不存在的时候才创建,如果存在同名就不再执行该语句
-- create_specification是建库的一些选项
-- 关键字不区分大小写
CREATE {DATABASE} [IF NOT EXISTS] db_name
  [create_specification [, create_specification] ...]
  • 创建一名为itcast的数据库
mysql> create database itheima;                          /* utf8 */
  • 创建一个使用 latin1 字符集的数据库
mysql> create database itheima character set latin1; 

6.3修改数据库

-- 修改字符集, 不能改名
alter database itcast character set utf8;

6.4删除数据库

drop database itcast;

7. 表的CURD

对表本身进行操作:创建,查看,修改,删除

7.1 查看表

  • 查看当前数据库下的数据库表

    – 当前使用的数据库下的表 mysql> show tables;

  • 查看指定表的创建语句

    mysql> show create table 表名;

  • 查看表结构

    mysql> desc 表名;

7.2创建表

mysql中表名区分大小写, 列名不区分大小写

  • 数据类型

20180606134721859.png 20180606134730934.png

  • float/double: 指定精确到小数点以后第几位, 比如: 精确到后3位
  • 通过计算得到一个数据: 12.345678
  • 这个数的678会被抹掉
  • decimal
  • 完整的保存精度, 最少有小数后有两位
  • 12.3 保存为: 12.30

20180606133023230.png 20180606133307614.png

  • 创建表
    create table 表名(
      列名 text [default 'xxx'],
      列名 类型 [default value],
      类名 类型 [default value],
      ......
    );
    

7.3修改表

  • 修改表名

    -- oracle和mysql相同
    rename table oldN to newN;
    
  • 添加一个字段

    -- oracle
    alter table 表名 add 列名 列的类型;
    
    -- mysql
    alter table 表名 add column 列名 列的类型;
    
  • 修改一个字段

    -- oracle
    alter table 表名 modify 列名 列的类型;
    
    -- mysql
    alter table 表名 modify column 列名 列的类型;
    
  • 删除一个字段

    -- mysql和oracle相同
    alter table 表名 drop column ;
    
    
    -- mysql中没有对对字段的rename操作
    
  • 修改表的字符集

    alter table 表名 character set utf8;
    

7.4 删除表

drop table 表名;
-- oracle中可以这么做, mysql中不行
drop table 表名 purge

8. 表数据的CURD

  • 插入数据

    • 表名后的列名什么时候可以省略?
    • 在values(列的值, 列的值, ….)中将表有的字段值都指定出来的时候, 列名可以省略
    insert into 表名[(列名, 列名, ...)] values(列的值, 列的值, ....);
    
  • 更新数据

    update 表名 set 列名=新值 where 列名=;
    
  • 删除数据

    delete from 表名; -- 删除所有行
    delete from 表名 where 列名=; -- 删除满足条件的行
    
  • 查询数据

    select *|列名|表达式 from 表名 where 条件 group by 列名 having 条件 order by asc|desc;
    
  • 练习

    • 创建数据库 student 表
      create table student(
        id int,
        name varchar(20),
        chinese int,
        english int,
        math int
      );
      
    • 插入数据
      insert into student(id,name,chinese,english,math) values(1, '范建',80,85,90);
      insert into student(id,name,chinese,english,math) values(2,'罗况',90,95,95);
      insert into student(id,name,chinese,english,math) values(3,'杜子腾',80,96,96);
      insert into student(id,name,chinese,english,math) values(4,'范冰',81,97,85);
      insert into student(id,name,chinese,english,math) values(5,'申晶冰',85,84,90);
      insert into student(id,name,chinese,english,math) values(6,'郝丽海',92,85,87);
      insert into student(id,name,chinese,english,math) values(7,'郭迪辉',75,81,80);
      insert into student(id,name,chinese,english,math) values(8,'拎壶冲',77,80,79);
      insert into student(id,name,chinese,english,math) values(9,'任我行',95,85,85);
      insert into student(id,name,chinese,english,math) values(10,'史泰香',94,85,84);
      
  • 查询表中所有学生的信息。
  • 查询表中所有学生的姓名和对应的英语成绩。

将第二步查询结果中的重复成绩过滤掉。

在所有学生英语分数上加10分特长分。

统计每个学生的总分。

使用别名表示学生分数

查询姓名为何东的学生成绩

查询英语成绩大于90分的同学

查询总分大于250分的所有同学

查询英语分数在 85-95之间的同学。

查询数学分数为84,90,91的同学。

查询所有姓何的学生成绩。

查询数学分>85,语文分>90的同学。

对数学成绩排序后输出。

对总分排序后输出,然后再按从高到低的顺序输出

对姓何的学生成绩排序输出

统计一个班级共有多少学生?

统计数学成绩大于90的学生有多少个?

统计总分大于250的人数有多少?

统计一个班级数学总成绩?

统计一个班级语文、英语、数学各科的总成绩

统计一个班级语文、英语、数学的成绩总和

求一个班级数学平均分?

求一个班级总分平均分

求班级最高分和最低分

9. mysql函数的使用

9.1 日期函数

MySQL里面时间分为三类:时间、日期、时间戳(含有时分秒的sysdate)。

image-20191130180806388.png

    -- 当前时间: now() == sysdate()
    mysql> select sysdate() from dual;
    +---------------------+
    | sysdate()           |
    +---------------------+
    | 2019-12-02 09:03:42 |
    +---------------------+
    1 row in set (0.00 sec)
    
    mysql> select now() from dual;
    +---------------------+
    | now()               |
    +---------------------+
    | 2019-12-02 09:04:35 |
    +---------------------+
    1 row in set (0.00 sec)
    -- addtime(time, s) 给当前实际, 添加对应的秒数
    select addtime('09:04:35',20) from dual; 
    +------------------------+
    | addtime('09:04:35',20) |
    +------------------------+
    | 09:04:55               |
    +------------------------+
    
    -- 当前日期: 年, 月, 日
    mysql> select current_date() from dual;
    +----------------+
    | current_date() |
    +----------------+
    | 2019-12-02     |
    +----------------+
    1 row in set (0.00 sec)
    
    -- 当前时间: 时, 分, 秒
    mysql> select current_time() from dual;    
    +----------------+
    | current_time() |
    +----------------+
    | 09:08:10       |
    +----------------+
    1 row in set (0.00 sec)
    
    -- 时间戳
    mysql> select current_timestamp() from dual;    
    +---------------------+
    | current_timestamp() |
    +---------------------+
    | 2019-12-02 09:09:47 |
    +---------------------+
    1 row in set (0.00 sec)
    
    -- 将给定时间的日期取出
    select date(now()) from dual;                 
    +-------------+
    | date(now()) |
    +-------------+
    | 2019-12-02  |
    +-------------+
    1 row in set (0.00 sec)
    
    -- date_add(), 第二个参数的type: 天: day, 月:month, 年: year
    mysql> select date_add(now(), interval 1 day) from dual;               
    +---------------------------------+
    | date_add(now(), interval 1 day) |
    +---------------------------------+
    | 2019-12-03 09:14:57             |
    +---------------------------------+
    1 row in set (0.00 sec)
    
    mysql> select date_add(now(), interval 1 month) from dual;   
    +-----------------------------------+
    | date_add(now(), interval 1 month) |
    +-----------------------------------+
    | 2020-01-02 09:15:27               |
    +-----------------------------------+
    1 row in set (0.00 sec)
    
    mysql> select date_add(now(), interval 1 year) from dual;     
    +----------------------------------+
    | date_add(now(), interval 1 year) |
    +----------------------------------+
    | 2020-12-02 09:15:37              |
    +----------------------------------+
    1 row in set (0.00 sec)
    
    -- 计算两个日期的差值
    mysql> select datediff('2019-12-01 09:18:06', '2019-1-02 09:18:06'); 
    +-------------------------------------------------------+
    | datediff('2019-12-01 09:18:06', '2019-1-02 09:18:06') |
    +-------------------------------------------------------+
    |                                                   333 |
    +-------------------------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> select datediff('2018-12-01 09:18:06', '2019-1-02 09:18:06'); 
    +-------------------------------------------------------+
    | datediff('2018-12-01 09:18:06', '2019-1-02 09:18:06') |
    +-------------------------------------------------------+
    |                                                   -32 |
    +-------------------------------------------------------+
    1 row in set (0.00 sec)
    -- 单独显示当前年, 月, 日
    select year(now()) "年", month(now()) "月", day(now()) "日" from dual;
    -- 单独显示当前日期, 时间, 时间戳
    -- 显示昨天, 今天, 明天
    select  date_sub(now(), interval 1 day), now(), date_add(now(), interval 1 day) from dual;

9.2 字符串函数

image-20191130182700039.png

-- 字符串连接
    -- mydql中可以连接多个字符串, oracle中只能连接两个字符串
    mysql> select concat("hello", " world", " 你好,", "世界") from dual;
    +-------------------------------------------------+
    | concat("hello", " world", " 你好,", "世界")     |
    +-------------------------------------------------+
    | hello world 你好,世界                           |
    +-------------------------------------------------+
    
-- 大小写转换
    mysql> select ucase("hello"), lcase("WORLD") from dual;
    +----------------+----------------+
    | ucase("hello") | lcase("WORLD") |
    +----------------+----------------+
    | HELLO          | world          |
    +----------------+----------------+
    1 row in set (0.00 sec)
    
-- 字符串截取, 从左侧开始
    mysql> select left("hello,world", 5) from dual;                      
    +------------------------+
    | left("hello,world", 5) |
    +------------------------+
    | hello                  |
    +------------------------+
    1 row in set (0.00 sec)
    
    
-- 字符串比较
    mysql> select strcmp("abc", "bca") from dual;
    +----------------------+
    | strcmp("abc", "bca") |
    +----------------------+
    |                   -1 |  -- 小于
    +----------------------+
    1 row in set (0.00 sec)
    
    mysql> select strcmp("aaa", "aa") from dual;     
    +---------------------+
    | strcmp("aaa", "aa") |
    +---------------------+
    |                   1 | -- 大于
    +---------------------+
    1 row in set (0.00 sec)
    
    mysql> select strcmp("aaa", "aaa") from dual;
    +----------------------+
    | strcmp("aaa", "aaa") |
    +----------------------+
    |                    0 | -- 等于
    +----------------------+
    1 row in set (0.00 sec)

9.3 数学函数

image-20191130183602147.png – 向上取整 – mysql ceiling(小数) – oracle ceil(小数)

    -- 进制转换
    mysql> select conv(100, 10, 16) from dual; 
    +-------------------+
    | conv(100, 10, 16) |
    +-------------------+
    | 64                |
    +-------------------+
    
    -- 保留指定的小数位数, 可以四舍五入
    mysql> select format(12.345, 2) from dual;
    +-------------------+
    | format(12.345, 2) |
    +-------------------+
    | 12.35             |
    +-------------------+
    1 row in set (0.00 sec)
    
    -- 取集合中的最小值
    mysql> select least(12, 1, 3, 4, 0) from dual;
    +-----------------------+
    | least(12, 1, 3, 4, 0) |
    +-----------------------+
    |                     0 |
    +-----------------------+
    1 row in set (0.00 sec)
    
    -- 生成随机数
    -- 生成的随机数范围: 0-1
    mysql> select rand(now()) from dual;
    +--------------------+
    | rand(now())        |
    +--------------------+
    | 0.8633374812671333 |
    +--------------------+
    1 row in set (0.00 sec)

9.4 日期转换

    -- oracle 日期格式: yyyy-mm-dd hh24:mi:ss 不区分大小写
    to_char()  日期转字符串
    to_date()  字符串转日期
    
    -- mysql 日期格式: %Y-%m-%d %H:%i:%s    区分大小写
    date_format() 日期转字符串
    str_to_date() 字符串转日期
含义
%S、%s 两位数字形式的秒( 00,01, …, 59)
%i 两位数字形式的分( 00,01, …, 59)
小时 %H 24小时制,两位数形式小时(00,01, …,23)
%h 12小时制,两位数形式小时(00,01, …,12)
%k 24小时制,数形式小时(0,1, …,23)
%l 12小时制,数形式小时(0,1, …,12)
%T 24小时制,时间形式(HH:mm:ss)
%r 12小时制,时间形式(hh:mm:ss AM 或 PM)
%p AM上午或PM下午
%W 一周中每一天的名称(Sunday,Monday, …,Saturday)
%a 一周中每一天名称的缩写(Sun,Mon, …,Sat)
%w 以数字形式标识周(0=Sunday,1=Monday, …,6=Saturday)
%U 数字表示周数,星期天为周中第一天
%u 数字表示周数,星期一为周中第一天
%d 两位数字表示月中天数(01,02, …,31)
%e 数字表示月中天数(1,2, …,31)
%D 英文后缀表示月中天数(1st,2nd,3rd …)
%j 以三位数字表示年中天数(001,002, …,366)
%M 英文月名(January,February, …,December)
%b 英文缩写月名(Jan,Feb, …,Dec)
%m 两位数字表示月份(01,02, …,12)
%c 数字表示月份(1,2, …,12)
%Y 四位数字表示的年份(2015,2016…)
%y 两位数字表示的年份(15,16…)
文字输出 %文字 直接输出文字内容
  • date类型装换为varchar类型

    -- date_format(日期, fmt)
    
    mysql> select date_format(now(), '%Y/%m/%d %H:%i:%s') from dual;   
    +-----------------------------------------+
    | date_format(now(), '%Y/%m/%d %H:%i:%s') |
    +-----------------------------------------+
    | 2019/12/02 10:07:37                     |
    +-----------------------------------------+
    
  • varchar类型转换为date类型

    -- 参数fmt的个数应该和日期字符串的形式一致
    -- str_to_date(日期字符串, fmt)
    mysql> select str_to_date("2019/12/02 10:07:37", "%Y/%m/%d %H:%i:%s") from dual;  
    +---------------------------------------------------------+
    | str_to_date("2019/12/02 10:07:37", "%Y/%m/%d %H:%i:%s") |
    +---------------------------------------------------------+
    | 2019-12-02 10:07:37                                     |
    +---------------------------------------------------------+
    1 row in set (0.00 sec)
    

10. 多表查询

    -- 分组函数
    count(); -- 求总数
    avg();     -- 求平均值
    sum();       -- 求和
    min();       -- 最小值
    max();     -- 最大值
    
    -- having 必须出现在group by 后边, 不能写where
    -- where 写在 from 的后边
    -- order by: 默认升序 asc, 降序 desc
    select 列名|表达式 as "别名" from 表名 "表的别名" where 表达式 group by 列名 having 条件 order by asc | desc
    -- 求两个表的笛卡尔积 cross join
    -- 最简单的两个表查询
    select * from dept, emp;
    select * from dept cross join emp;

10.1 内连接 – inner join

显示部门名称, 部门编号, 员工编号,和员工姓名

-- mysql+oracle
select d.deptno, d.dname, e.empno, e.ename from dept d, emp e where d.deptno=e.deptno;
    
-- mysql+oracle
-- 将表之间的逗号替换为 inner join --> 简写为 join
-- 将 where 替换为 on
select d.deptno, d.dname, e.empno, e.ename from dept d  join emp e on d.deptno=e.deptno;

10.2 外连接 – outer join

外连接: 在多表查询的时候, 要通过where进行过滤, 有些表中的字段值不满足条件, 被过滤掉了, 不会显示在最终的结果集中, 必须使用外连接的方式, 才能够使其显示在结果集中.

按部门统计员工人数,显示如下信息:部门号,部门名称,人数(所有部门的人数都统计)

  • 左外连接 – left outer join
  -- oracle
  select d.deptno, d.dname, count(e.empno) from dept d, emp e where d.deptno=e.deptno(+) group by d.deptno, d.dname;
    
    -- mysql + oracle
    -- 表之间的逗号替换为:   left outer join -> outer 可以省略 -> left join
    -- where -> on
    select d.deptno, d.dname, count(e.empno) from dept d left outer join emp e on d.deptno=e.deptno group by d.deptno, d.dname;
  • 右外连接 – right outer join
    -- oracle
    select d.deptno, d.dname, count(e.empno) from dept d, emp e where e.deptno(+)=d.deptno group by d.deptno, d.dname;
    
    -- mysql + oracle
    -- 表之间的逗号替换为:   right outer join -> outer 可以省略 -> right join
    -- where -> on
    select d.deptno, d.dname, count(e.empno) from emp e right join dept d on e.deptno=d.deptno group by d.deptno, d.dname;
  • 全外连接 – full outer join

在多表查询的时候, 要通过where进行过滤, 有些表中的字段值不满足条件, 被过滤掉了, 不会显示在最终的结果集中, 不知道的那个表的字段不满足条件或者是左侧不满足条件或右侧表不满足条件, 需要将这些不满条件对数据全部显示到结果集中, 可以使用全外连接.

  • 两个表互相补充
      -- 在mysql中不支持全外连接, oracle中是支持的
    
      -- full outer join -> 简写: full join
      -- 有可能emp表给dept提供补充, 也有可能dept给emp提供补充
      select d.deptno, d.dname, count(e.empno) from emp e full join dept d on e.deptno=d.deptno group by d.deptno, d.dname;

10.3 自连接

查询员工、老板信息,显示: xxx的老板是xxx

-- oracle
select e.ename "员工", nvl(b.ename, 'jump') "领导"  from emp e, emp b where e.mgr=b.empno(+); 
 
-- mysql
-- mysql 中的ifnull 等价于 oracle 中的 nvl
select e.ename "员工", ifnull(b.ename, 'jump') "领导"  from emp e left join emp b on e.mgr=b.empno; 

11. 表的约束

create table 表名(
    列名 列的类型 default 默认值,
    列名 列的类型,
    列名 列的类型
);

11.1 约束种类

mysql中常用的约束有五种:

  • 主键约束 primary key

    • 非空 + 唯一
  • 主键自动增长 auto_increment

    • 给主键用的, 只有列是主键才能加这个约束
    • 主键是数字的时候使用
  • 唯一约束  unique

  • 非空约束  not null

  • 外键约束  foreign key

  • 检查约束 check (在MySQL中语法保留,但没有效果)

11.2 约束的使用

create table persion(
    id int,            -- 主键, 自动增长
    age int,            -- 非空
    name varchar(20),    -- 唯一
    deptno int        -- 外键
);
  • 表级别的约束
-- auto_increment只能放到列的位置
-- not null 非空只能在列上添加约束
create table persion(
    id int auto_increment,            -- 主键, 自动增长
    age int not null,            -- 非空
    name varchar(20),    -- 唯一
    deptno int,        -- 外键
    constraint pk_id_xxx primary key(id) ,
    constraint un_name_xxx unique(name),
    constraint fk_deptno_xx foreign key(deptno) references dept(deptno)
);
  • 列级别的约束
create table persion1(
    id int primary key auto_increment,            -- 主键, 自动增长
    age int not null,            -- 非空
    name varchar(20) unique,    -- 唯一
    deptno int references dept(deptno)    -- 外键
);

12. 事务

在mysql中事务默认是自动提交的,oracle中默认是手动提交的。

  • 原子性
  • 一致性
  • 隔离性
  • 永久性
-- 修改事务提交方式
 
-- 手动提交
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
 
-- 提交数据
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
 
-- 数据回滚
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
 
-- 自动提交
mysql> set autocommit=1;
Query OK, 0 rows affected (0.00 sec)

13. mysql API

  1. 初始化连接环境
  2. 连接mysql的服务器
  3. 执行sql语句
  • 查询
  • 插入
  • 更新
  • 删除
  • 创建/删除/修改数据库表
  1. 如果是插入/删除/修改数据等操作只能看到状态
  • 成功
  • 失败
  1. 如果sql语句是查询, 得到结果集
  2. 遍历结果集
  3. 释放资源
  • 初始化连接环境
// 参数: NULL
// 返回值: 返回函数申请的内存的地址
MYSQL *mysql_init(MYSQL *mysql)  
  • 连接mysql服务器
 // 返回值: 失败-> NULL, 成功了-> 返回值和第一个参数的地址相同
MYSQL *mysql_real_connect(
                MYSQL *mysql,     // mysql_init函数的返回值
                // 本地: localhost, 远程连接:192.168.xx.xx;
                const char *host,     // mysql服务器地址, IP/主机名      
                const char *user,     // mysql数据用户名, root       
                const char *passwd,   // root用户的密码
                const char *db,       // 数据库的名字       
                // 如果port==0, 使用默认端口, !=0是使用指定的端口
                unsigned int port,    // 数据库的端口, 默认3306    
                const char *unix_socket,   // NULL  
                unsigned long client_flag  // 0
);
  • 执行sql语句
// 添删查改的sql语句都是可以执行的
// 参数:
//         mysql: mysql_real_connect()函数的返回值
//      query: sql语句, 语句的结尾不要加 ;
// 返回值: 成功-> 0, 失败->非0
int mysql_query(MYSQL *mysql, const char *query);
  • 获取结果集
// 将结果集保存到本地内存中
// 返回值: 错误->null, 成功->非空
// 参数 mysql: mysql_real_connect() 返回值
// 结果集中保存了多条记录, 每条记录中有若干个字段
MYSQL_RES *mysql_store_result(MYSQL *mysql);
  • 得到结果集的列数
unsigned int mysql_num_fields(MYSQL_RES *result)
  • 获取表头 -> 列名(字段名)
/ mysql.h
typedef struct st_mysql_field {
  char *name;                 /* Name of column */
  char *org_name;             /* Original column name, if an alias */
  char *table;                /* Table of column if column was a field */
  char *org_table;            /* Org table name, if table was an alias */
  char *db;                   /* Database for table */
  char *catalog;          /* Catalog for table */
  char *def;                  /* Default value (set by mysql_list_fields) */
  unsigned long length;       /* Width of column (create length) */
  unsigned long max_length;   /* Max width for selected set */
  unsigned int name_length;
  unsigned int org_name_length;                                                                                        
  unsigned int table_length;
  unsigned int org_table_length;
  unsigned int db_length;
  unsigned int catalog_length;
  unsigned int def_length;
  unsigned int flags;         /* Div flags */
  unsigned int decimals;      /* Number of decimals in field */
  unsigned int charsetnr;     /* Character set */
  enum enum_field_types type; /* Type of field. See mysql_com.h for types */
  void *extension;
} MYSQL_FIELD;
 
// 返回值 中保存了所有的字段名, 返回值是一个数组
MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result);
 
MYSQL_FIELD *fields = mysql_fetch_fields(result);
for(int i=0; i<num; ++i) {
    fields[i].name
}
  • 遍历结果集
typedef char** MYSQL_ROW;
// 函数每调用一次, 从结果集中取出一条记录(行)
// 参数: 结果集, mysql_store_result()返回值
// 返回值: char* row[], char**执向一个指针数组, 数组中的每一个元素都是一个字符串, 字符串就是字段值
//        不管字段原来是什么类型, 结果集中都是以字符串形式保存的
// 如果还有下一行返回非空, 没有下一行, 或者失败了返回NULL
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
  • 资源回收
// 参数是 mysql_store_result() 函数的返回值
void mysql_free_result(MYSQL_RES *result);
 
// 参数是: mysql_init() 函数的返回值
void mysql_close(MYSQL *mysql);
  • 字符编码
// 获取字节编码
const char *mysql_character_set_name(MYSQL *mysql);
// 设置字节编码
// csname: 编码的名字, utf8
int mysql_set_character_set(MYSQL *mysql, char *csname);
  • 事务操作
// mode==0 -> 手动提交, mode1 -> 自动提交事务
my_bool mysql_autocommit(MYSQL *mysql, my_bool mode);
my_bool mysql_commit(MYSQL *mysql);
my_bool mysql_rollback(MYSQL *mysql);
  • 打印错误信息
// 返回错误的描述
const char *mysql_error(MYSQL *mysql);
// 返回错误的编号
unsigned int mysql_errno(MYSQL *mysql);
  • 需要的头文件
#include <mysql.h>
 
// 动态库名: libmysqlclient.so
// 静态库名: libmysqlclient.a
  • 搜索文件
find 路径 -name 文件名
locate 文件名  
    
# centos
# 切换到root下安装
yum install mlocate
updatedb    # 只需要做一次, 安装完成之后做
  • 完整实例
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <mysql.h>
 
int main() {
    MYSQL *mysql = mysql_init(NULL);
    if (mysql == nullptr) {
        printf("mysql_init() failed\n");
        return -1;
    }
    
    mysql_real_connect(mysql, "192.168.213.128", "root", "zzc123", "scott", 0, NULL, 0);
    if (mysql == NULL) {
        printf("mysql_real_connect() failed\n");
        return -1;
    }
    printf("服务器连接成功!\n");
    printf("原字符编码: %s\n", mysql_character_set_name(mysql));
    mysql_set_character_set(mysql, "utf8");
    printf("现字符编码: %s\n", mysql_character_set_name(mysql));
    
    int ret = mysql_query(mysql, "select * from emp");
    
    if (ret != 0) {
        printf("mysql_query(select) failed: %s\n", mysql_error(mysql));
        return -1;
    }
    
    MYSQL_RES *res = mysql_store_result(mysql);
    int colNum = mysql_num_fields(res);
    //fields是一个结构体数组
    MYSQL_FIELD *fields = mysql_fetch_fields(res);
    
    for (int i = 0; i < colNum; i ++) {
        //遍历结构体内名字字段
        printf("%s\t", fields[i].name);
    }
    printf("\n");
    
    //读取每一行
    //二级指针
    MYSQL_ROW row;
    while ((row = mysql_fetch_row(res)) != NULL) {
        for (int i = 0; i < colNum; i ++) {
            printf("%s\t", row[i]);
        }
        printf("\n");
    }
    
    //释放结果集
    mysql_free_result(res);
    
    //设置事务手动提交
    mysql_autocommit(mysql, 0);
    
    //将下面的四个操作设置为事务
    //插入数据
    int fl1 = mysql_query(mysql, "insert into dept values(11, '海军', 'china')");
    int fl2 = mysql_query(mysql, "insert into dept values(12, '革命军', 'china')");
    int fl3 = mysql_query(mysql, "insert into dept values(13, '马戏团', 'china')");
    //更新数据
    int fl4 = mysql_query(mysql, "update dept set dname='群众' where loc='china'");
    
    //全部成功
    if (!fl1 && !fl2 && !fl3 && !fl4) {
        //提交事务
        mysql_commit(mysql);
    } else {
        //事务回滚
        mysql_roolback(mysql);
    }
    
    //释放资源
    mysql_close(mysql);
    
    return 0;
}
  • mysql和oracle区别

    • 结构不同

      • msyql 基于数据库

        • 表存储在数据库中
      • oracle 基于用户的

        • 表属于用户
    • mysql没有表空间, oracle有表空间

    • 管理员

      • mysql

        • root
      • oralce

        • sys -> 管理员, 身份 sysdba
        • system -> 管理员, 登录的时候需要使用normal身份登录
        • 其他的普通用户
    • 事务

      • oracle默认手动提交

        • occi接口 (C++接口), 这个接口中是自动提交事务的
      • mysql中默认是自动提交

    • sql语句

      • 外连接

        • oralce中可以使用 (+)
        • mysql中必须使用 , 不支持(+)
          • right outer join -> oracle也支持这种写法
          • left outer join
        • mysql不支持全外连接, oracle支持的
          • full outer join
    • 函数:

      • nvl -> oralce

      • ifnull -> mysql

      • 日期

      • 字符串

      • 数学函数

    • 建表的时候的约束指定

      • 都有:

        • 主键 -> primary key
        • 非空: not null
        • 唯一性: unique
        • 外键约束: foreign key
      • 不同:

        • oralce:
          • check, 在mysql中也有, 但是不起作用
        • mysql
          • 主键自动增长: auto_increment

            • 需要和主键约束一起使用
    • 删除表

      • oracle

        • drop talbe 表名 purge;
      • msyql

        • drop talbe 表名; –> 不能使用 purge
    • 字段的修改

      • oralce

        • 列的添加
          alter table 表名 add 列名 列的属性;
          alter table 表名 modify 列名 列的属性;
          
      • mysql

        • 列的添加修改
          alter table 表名 add column 列名 列的属性;
          alter table 表名 modify column 列名 列的属性;