mysql

53 阅读11分钟

image.png

SQL 语句主要分为:

  • DQL:数据查询语言,用于对数据进行查询,如 select
  • DML:数据操作语言,对数据进行增加、修改、删除,如 insert、update、delete
  • TPL:事务处理语言,对事务进行处理,包括 begin transaction、commit、rollback
  • DCL:数据控制语言,进行授权与权限回收,如 grant、revoke
  • DDL:数据定义语言,进行数据库、表的管理等,如 create、drop

注意:

  • 对于开发人员来说,重点是数据库的增、删、改、查。必须熟练编写 DQL、DML,能够编写 DDL 完成数据库、表的操作,其它操作如 TPL、DCL 了解、会用即可。
  • SQL 语言不区分大小写

MySQL 的配置文件

配置文件路径为:/etc/mysql/mysql.conf.d/mysqld.cnf

数据类型

常用数据类型:

  • 整数:int,bit
  • 小数:decimal
  • 字符串:varchar,char
  • 日期时间:date, time, datetime
  • 枚举类型 (enum)

数据类型使用说明:

  • decimal 表示浮点数,如 decimal(5, 2) 表示共存 5 位数,小数占 2 位。
  • char 表示固定长度的字符串,如 char(3),如果填充'ab'时会补一个空格为'ab ',3 表示字符数。
  • varchar 表示可变长度的字符串,如 varchar(3),填充'ab'时就会存储'ab',3 表示字符数。
  • 对于图片、音频、视频等文件,一般不存储在数据库中,而是上传到服务器上,然后在表中存储这个文件的保存路径。
  • text 表示存储大文本,当字符大于 4000 时推荐使用,例如文章正文内容。

数据约束

约束是指数据在数据类型限定的基础上额外增加的要求。

常见的约束:

  • 主键 primary key: 物理上存储的顺序。MySQL 建议所有表的主键字段都叫 id,类型为 int unsigned。
  • 非空 not null: 此字段不允许填写空值。
  • 惟一 unique: 此字段的值不允许重复。
  • 默认 default: 当不填写字段对应的值会使用默认值,如果填写时以填写为准。
  • 外键 foreign key: 对关系字段进行约束,当为关系字段填写值时,会到关联的表中查询此值是否存在,如果存在则填写成功,如果不存在则填写失败并抛出异常。

image.png

image.png

登录和登出数据库

mysql -u root -p

说明:

  • -u 后面是登录的用户名
  • -p 后面是登录密码,如果不填写,回车之后会提示输入密码

登出 (退出) 数据库

quit 或 exit 或 \q

数据库操作的 SQL 语句

查看所有数据库

show databases;

创建数据库

create database 数据库名 charset=utf8mb4;

-- 例如:

create database hello charset=utf8mb4;

使用数据库

use 数据库名;
-- 例如:
use hello;

 查看当前使用的数据库

select database();

删除数据库 - 慎重

drop database 数据库名;
-- 例如:
drop database hello;

操作表结构的 SQL 语句

查看当前数据库中所有表

show tables;

创建表

create table users(
 id int unsigned primary key auto_increment not null,
 name varchar(20) not null,
 age tinyint unsigned default 0,
 height decimal(5,2),
 gender enum('男','女','其他')
);
create table 表名(
字段名称 数据类型  可选的约束条件,
column1 datatype contrai,
...
);

修改表 - 添加字段

alter table 表名 add 列名 类型 约束;
-- 例如:
alter table users add birthday datetime;

 修改表 - 修改字段类型

alter table 表名 modify 列名 类型 约束;
-- 例如:
alter table users modify birthday date not null;

说明:

  • modify: 只能修改字段类型或者约束,不能修改字段名

修改表 - 修改字段名和字段类型

alter table 表名 change 原名 新名 类型及约束;
-- 例如:
alter table users change birthday birth datetime not null;

change: 既能对字段重命名又能修改字段类型还能修改约束

修改表 - 删除字段

alter table 表名 drop 列名;
-- 例如:
alter table users drop birth;

操作表数据的 SQL 语句

#  查询所有列
select * from 表名;
-- 例如:
select * from users;

#  查询指定列
select1,列2,... from 表名;
-- 例如:
select id,name from users;

添加数据

#  全列插入:值的顺序与表结构字段的顺序完全一一对应
insert into 表名 values (...)
-- 例如:
insert into users values(0, '花木兰', default, default, '女');

#  部分列插入:值的顺序与给出的列顺序对应
insert into 表名 (列1,...) values(值1,...)
-- 例如:
insert into users(name, age) values('貂蝉', 15);

#  全列多行插入
insert into 表名 values(...),(...)...;
-- 例如:
insert into users values(0, '王昭君', 16, 1.65, '女'),(0, '杨玉环', 20, 1.60, '女');

#  部分列多行插入
insert into 表名(列1,...) values(值1,...),(值1,...)...;
-- 例如:
insert into users(name, height) values('刘邦', 1.70),('项羽', 1.75);

说明:

  • 主键列是自动增长,但是在全列插入时需要占位,通常使用空值 (0 或者 null 或者 default)
  • 在全列插入时,如果字段列有默认值可以使用 default 来占位,插入的数据就是之前设置的默认值

修改数据

update 表名 set1=1,列2=2... where 条件
-- 例如:
update users set age = 18, gender = '女' where id = 6;

删除数据

delete from 表名 where 条件
-- 例如:
delete from users where id=5;
  • 登录数据库:mysql -uroot -p
  • 退出数据库:quit 或者 exit 或者 ctr + d
  • 创建数据库:create database 数据库名 charset=utf8;
  • 使用数据库:use 数据库名;
  • 删除数据库:drop database 数据库名;
  • 创建表:create table 表名 (字段名 字段类型 约束,...);
  • 修改表 - 添加字段:alter table 表名 add 字段名 字段类型 约束
  • 修改表 - 修改字段类型:alter table 表名 modify 字段名 字段类型 约束
  • 修改表 - 修改字段名和字段类型:alter table 表名 change 原字段名 新字段名 字段类型 约束
  • 修改表 - 删除字段:alter table 表名 drop 字段名;
  • 删除表:drop table 表名;
  • 查询数据:select * from 表名; 或者 select 列 1,列 2,... from 表名;
  • 插入数据:insert into 表名 values (...) 或者 insert into 表名 (列 1,...) values(值 1,...)
  • 修改数据:update 表名 set 列 1=值 1,列 2=值 2... where 条件
  • 删除数据:delete from 表名 where 条件

as 关键字

就是给字段取一个别名,一般是为了可读性,或者多表关联查询有同名字段时使用。

select id as 序号, name as 名字, gender as 性别 from users;

使用 as 给表起别名

-- 如果是单表查询 可以省略表名
select id, name, gender from users;

-- 表名.字段名
select users.id,users.name,users.gender from users;

-- 可以通过 as 给表起别名 
select u.id,u.name,u.gender from users as u;

distinct 关键字

distinct 可以去除重复数据行

select distinct1,... from 表名;

-- 例: 查询用户表的性别
select name, gender from users;

-- 如果有重复数据,可以使用 distinct 进行去重
select distinct name, gender from users;
  • as 关键字用来给表中字段或者表名起别名
  • distinct 关键字用来去除重复的数据行。

where 条件查询语法格式如下:

select * from 表名 where 条件;
-- 例如:
select * from users where id = 1;
-- 查询编号大于3的用户:
select * from users where id > 3;

-- 查询编号不大于4的用户:
select * from users where id <= 4;

-- 查询姓名不是“曹操”的用户:
select * from users where name != '曹操';

-- 查询被删除的用户:
select * from users where deleted=1;

逻辑运算符查询

-- 查询编号大于3的女用户:
select * from users where id > 3 and gender='女';

-- 查询编号小于4或未被删除的用户:
select * from users where id < 4 or deleted=0;

-- 查询年龄不在10岁到15岁之间的用户:
select * from users where not (age >= 10 and age <= 15);

模糊查询

  • like 是模糊查询关键字
  • %表示任意多个任意字符
  • _表示一个任意字符
-- 查询姓刘的学生:
select * from users where name like '刘%';

-- 查询姓刘并且“名”是一个字的学生:

select * from users where name like '刘_';

-- 查询姓刘或叫操的学生:
select * from users where name like '刘%' or name like '%操';

范围查询

  • between .. and .. 表示在一个连续的范围内查询
  • in 表示在一个非连续的范围内查询
-- 查询id为3至7的用户:
select * from users where id between 3 and 7;

-- 查询id不是3至7的女性:
select * from users where (not id between 3 and 7) and gender='女';

-- 查询id为3和7的用户:
select * from users where id in (3, 7);

空判断查询

  • 判断为空使用:is null
  • 判断非空使用:is not null
-- 查询没有填写身高的学生:
select * from users where height is null;
  • 常见的比较运算符有 >、<、>=、<=、!=
  • 逻辑运算符 and 表示多个条件同时成立则为真,or 表示多个条件有一个成立则为真,not 表示对条件取反
  • like 和%结合使用表示任意多个任意字符,like 和_结合使用表示一个任意字符
  • between-and 限制连续性范围 in 限制非连续性范围
  • 判断为空使用:is null
  • 判断非空使用:is not null

排序查询

select * from 表名 order by1 asc|desc [,列2 asc|desc,...]
  • 先按照列 1 进行排序,如果列 1 的值相同时,则按照 列 2 排序,以此类推
  • asc 从小到大排列,即升序
  • desc 从大到小排序,即降序
  • 默认按照列值从小到大排列(即 asc 关键字)
-- 查询未删除男性信息,按id降序:
select * from users where gender='男' and deleted=0 order by id desc;

-- 显示所有的用户信息,先按照年龄从大->小排序,当年龄相同时 按照身高从高->矮排序:
select * from users order by age desc, height desc;
  • 排序使用 order by 关键字
  • asc 表示升序
  • desc 表示降序

分页查询的语法

select * from 表名 limit start,count
  • limit 是分页查询关键字
  • start 表示开始行索引,默认是 0
  • count 表示查询条数
-- 查询前3行男性信息:
select * from users limit 0,3;
-- 简写
select * from users limit 3;

分页查询原理

假设,当前页 current_page=1,要求每页显示 2 条数据,也就是 page_size=2,那么

  • current_page=1 页查询的数据就是 0, 2
  • current_page=2 页查询的数据就是,2, 2
  • current_page=3 页查询的数据就是,4, 2

其他依次类推,可得到公式,limit 的值就是:(当前页-1) * 每页显示条数, 每页显示条数

select * from users limit (current_page-1) * current_page, page_size;

-- 例如
select * from users limit 0, 2;
select * from users limit 2, 2;
select * from users limit 4, 2;
select * from users limit 6, 2;

用来对数据进行统计和计算,经常会结合分组 (group by) 查询来使用。

常用的聚合函数:

  • count(col): 表示求指定列的总行数
  • max(col): 表示求指定列的最大值
  • min(col): 表示求指定列的最小值
  • sum(col): 表示求指定列的和
  • avg(col): 表示求指定列的平均值

求总行数

-- 返回非NULL数据的总行数.
select count(height) from users; 
-- 返回总行数,包含null值记录;
select count(*) from users;

求最大值

-- 查询ID最大值
select max(id) from users;
-- 查询最小ID
select min(id) from users;
-- 查询男性的总身高
select sum(height) from users where gender = '男';

-- 平均身高
select sum(height) / count(*) from users where gender = '男';
-- 求男性的平均身高, 聚合函数不统计null值,平均身高有误
select avg(height) from users where gender = '男';

-- 求男性的平均身高, 包含身高是nullselect avg(ifnull(height,1.80)) from users where gender = '男';

连接查询

  • 内连接(inner join)查询
  • 左连接(left join)查询
  • 右连接(right join)查询
  • 全连接 (full,join,注意:MySQL 中没有)
  • 自连接查询
CREATE TABLE `articles` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `category_id` int(11) DEFAULT NULL,
  `title` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `articles` (`id`, `category_id`, `title`)
VALUES
    (1,1,'过节不出门,出门不过节'),
    (2,2,'人类踏上火星指日可待'),
    (3,4,'天生我才必有用');

CREATE TABLE `categories` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `categories` (`id`, `name`)
VALUES
    (1,'旅行'),
    (2,'科技'),
    (3,'娱乐');

左连接查询

以左表为主根据条件查询右表数据,如果根据条件查询右表数据不存在使用 null 值填充

select 字段 from 表 1 left join 表 2 on 表 1.字段 1 = 表 2.字段 2

使用左连接查询文章表与分类表:

select * from articles as a left join categories as c on a.category_id = c.id;

image.png

右连接查询

select 字段 from 表1 right join 表2 on 表1.字段1 = 表2.字段2

select * from articles as a right join categories as c on a.category_id = c.id;

image.png

内连接,就是查询两个表中符合条件的共有记录

select 字段 from1 inner join2 on1.字段1 = 表2.字段2

说明:

  • inner join 就是内连接查询关键字
  • on 就是连接查询条件

例 1:使用内连接查询文章表与分类表:

select * from articles as a inner join categories as c on a.category_id = c.id;

-- 也可以不定义别名
select * from articles inner join categories on articles.category_id = categories.id;

image.png

自连接查询

左表和右表是同一个表,根据连接查询条件查询两个表中的数据。

CREATE TABLE `department` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `parent_id` int(11) DEFAULT 0,
  `name` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `department` (`id`, `parent_id`, `name`)
VALUES
    (1,0,'研发部'),
    (2,0,'市场部'),
    (3,1,'后端组'),
    (4,1,'前端组'),
    (5,1,'移动端开发组'),
    (6,2,'销售组'),
    (7,2,'售后组');

查询研发部下面所有二级部门

select x.id, x.name, x.parent_id, y.name from department as x inner join department as y on x.parent_id = y.id where y.name = '研发部';

image.png

子查询的使用

例 1. 查询大于平均年龄的用户:

select * from users where age > (select avg(age) from users);

查询文章所在分类的所有分类名字:

select id, name from categories where id in (select category_id from articles);

查找年龄最大,身高最高的用户:

select * from users where (age, height) =  (select max(age), max(height) from users