# MySQL [MySQL 教程 | 菜鸟教程](https://www.runoob.com/mysql/mysql-tutorial.html) ## docker 安装mysql 1. 创建 docker-compose.yml ```sh vim docker-comopse.yml === services: mysql: image: mysql restart: on-failure environment: - MYSQL_ROOT_PASSWORD=Aa123456 - MYSQL_DATABASE=mybase - MYSQL_USER=hxx - MYSQL_PASSWORD=Aa123456 - TZ=Asia/Shanghai - character-set-server=utf8mb4 - collation-server=utf8mb4_unicode_ci ports: - '3307:3306' volumes: - ./data:/var/lib/mysql # 数据挂载 - ./init:/docker-entrypoit-initdb.d/ # 初始脚本 === ``` 2. 创建授权 root 用户可以远程链接的脚本 ```sh mkdir init vim init/remote.sql === -- GRANT ALL privileges on *.* TO 'root'@'%'; ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native-pasword BY 'Aa123456'; === ``` * 错误 Client does not support authentication protocol requested by server; consider upgrading MySQL client ```sh mysql -u root -p ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码'; # ALTER USER 'root' IDENTIFIED WITH mysql_native_password BY '你的密码'; flush privileges; # mysq> 加一个闪烁的光标等待命令的输入, 输入 exit 或 quit 退出登录 ``` ## 语法 * 大小写不敏感 * 可以单行/多行, 以`;`结束 * 注释 * 单行: `-- 注释内容` * 单行: `# 注释内容` * 多行: `/* 多行内容 */` ## 数据库操作 ```mysql # 查看数据库 show databases; # 使用数据库 use 数据库名; # 创建数据库 create database 数据库名 [charset utf8]; # 删除数据库 drop database 数据库名; # 查看当前使用的数据库 select database(); ``` ## 表操作 ### 查 ```mysql # 查看有哪写表, 需要先选择库 show tables; # 查看表的结构 desc 表名; ``` ### 增 ```mysql # 创建表 create table 表名称( 列名称 列类型, 列名称 列类型, ...... ); /* 列类型有: int 整数 float 浮点数 varchar(长度) 文件,长度为数字, 做最大长度限制 date 日期类型 timestamp 时间戳 */ # 复制表结构 create table 新表名 like 旧表名; # 复制表 create table 新表名 as (select * from 旧表名); ``` **通用字段** * id * create_time * creator * update_time: 默认值可以为 CURRENT_TIMESTAMP * update_by * remark 一张表的字段不宜超过20个,超过考虑拆分 ### 删 ```mysql # 删除表 drop table 表名称; drop table if exists 表名称; ``` ### 改 ```mysql # 增加字段 alter table 表名 add 字段名 类型; # 删除字段 alter table 表名 drop 字段名; # 更改字段类型 alter table 表名 modify 字段 类型; # 更改字段名 alter table 表名 change 旧字段 新字段 类型; ``` ## 增删改查 ### 增 ```mysql insert into 表名 [(字段列表)] values (值列表); -- 如果为所有字段新增数据, 不需要写字段列表 -- null 说明由系统自动生成标识列 -- 如果字段非空, 但有默认值, 可以不赋值 -- 非空字段, 没有默认值, 一定要赋值 -- 字符串一定要加引号, 数字可加可不加 ``` ```mysql insert into users values (null, '马九', 22, '男', '马家村', 0); -- 或者 insert into users (name, age, address) values ('马十', 21, '马家村'); # 插入多条 insert into 表名 [(字段列表)] values (值列表), (值列表), ...; ``` ### 删 ```mysql delete from 表名 where 条件; # 清空表 delete from 表名; ``` ```mysql DELETE from users where name = '马十'; DELETE from users where id in (1, 3); ``` ### 改 ```mysql updata 表名 set 字段 = 新值, 字段 = 新值 where 条件; -- 一定要加上条件, 不加条件所有的都被修改了 ``` ```mysql update users set age = 20 where id = 2; -- 使用表达式 update users set age = age + 1 where id = 1; ``` ```mysql UPDATE torrent SET url = REPLACE(url, 'mikanani.me', 'mikanime.tv') WHERE url LIKE '%mikanani.me%'; ``` ### 查 ```mysql -- 注释为双横线加空格 select 字段 from 表名 [where 条件]; -- 条件没有可以不写 -- 返回的结果是虚拟表 -- 在sql中. 逻辑等和赋值都是用=号 -- 逻辑与 and -- 逻辑或 or -- 逻辑非 not ``` ```mysql select * from users; select id, name, gender from users; select * from users where id = 2; select * frm users where id = 2 or id = 3; select * from users where gender = '男' and age > 20; select * from users where id in (2, 3, 4, 5); -- id在2, 3, 4, 5 范围内 select * from users where id not in (1, 2); -- id 不包括2, 3, 4, 5 ``` ## 其他常用函数 ### 统计 ```mysql -- 统计所有数据条数 select count(*) from users; -- 只统计非空的数据调数, 过滤null select count(gender) from users; -- 查询最大 select max(age) from users; -- 查询最小 select min(age) from users; -- 求平均, 数值有效 select avg(age) from users; ``` ### 排序 ```mysql -- asc升序, 默认升序可以不写, desc倒序 select * from users order by id [asc]; select * from users order by id desc; ``` ```mysql # 排序 select 列|聚合函数|* from 表 [where 条件] [group by 列] order by 列 [asc|desc]; # asc 升序, 默认, 可以不写 # desc 倒序 ``` ### 分页 ```mysql select * from users limit m; -- 前m条 select * from users limit m, n; -- 查询m+n条记录,去掉前m条,返回后n条记录.m的值越大,查询的性能会越低 select * from users limit 3 offset 0; -- 从第1条开始, 向下查询3条 -- offset 偏移 -- 当m非常大时, 要先查询m+n条记录 , 再取n条, 非常慢, 可以进行优化 select * from users limit 10000, 100; -- 优化思想, 先定位id select * from users where id >100001 limit 100; ``` ```mysql # 分页查询 select 列|聚合函数|* from 表 [where 条件] [group by 列] order by 列 [asc|desc] limit n[,m]; # 只有n, 取n条 # n, m 跳过n条, 取m条 ``` ### 分组聚合 ```mysql # 分组聚合 select 字段|聚合函数 from 表名 [where 条件] group by 列; # group by 出现的哪个列, 只有这个列能用在字段中 # 按照 group by后面的条件进行分组 /* 聚合函数有: sum(列) 求和 avg(列) 平均 min(列) 最小 max(列) 最大 count(列|*) 数量 */ # 按男女分组, 统计平均年龄 select gender, avg(age) from student group by gender; # 数值函数 # 四舍五入: round() # 向上取整: ceil() # 向下取整: floor() # 按部门求平均工资, 并且过滤出工资大于3000的 select depnum, ave(salary) as 平均工资 from emp group by depnum having 平均工资>3000; # HAVING 子句用于对分组结果进行过滤。它通常与 GROUP BY 子句一起使用,用于筛选聚合函数的结果。 # WHERE 子句用于在分组前对记录进行过滤 # as 命名 ``` **注意事项:** * select, from 必写 * where, group by, order by, limit 按须 * 执行顺序: from -> where -> group by 和聚合函数 -> select -> order by -> limit ### 去重 ```mysql # 从表中选择不重复的列 SELECT DISTINCT 字段 FROM 表名; # 多列,并且这些列的组合是唯一 SELECT DISTINCT column1, column2 FROM table_name; ``` ### 模糊查询 ```mysql # like # % 表示匹配多个字符 # _ 表示匹配单个字符 select * from 表名 where 字段 like '%字符%'; ``` ### 长度 ```mysql # 判断字符长度 select length('一'); # 获取姓名为两个中文的 SELECT * FROM users WHERE LENGTH(name)=6; ``` ### 运算符 ```mysql # select 后面 + - * / # 应用在数值类型 # 查询员工半年的工资 select name, salary*6 as 半年工资 from emp; # ifnull(要检查的表达式, 为null时的替代值) select name, (salary+ifnull(comm,0))*6 as 半年工资(加奖金) from emp; ``` ### 日期函数 ```mysql select month('2024-01-01'); select year('2024-01-01'); select day('2024-01-01'); select week('2024-01-01'); select now(); # 当前时间 # timestampdiff(格式, 开始时间, 结束时间) SELECT timestampdiff(DAY, '2024-01-01', NOW()); ``` ### 多表查询 ![](https://img.081024.xyz/6-MySQL-20240601234301884.jpg) #### 交叉连接/关联查询 速度比较慢 ```mysql # 交叉连接: cross join # 学生表和成绩表关联 select * from student cross join score where student.Sno=score.Sno; # cross join 返回的是笛卡尔积的数据,存在无意义的数据。所以用where过滤掉 # cross join 简写为逗号 select * from student, score where student.Sno=score.Sno; # 查询每个学生每门课程考多少分 select student.Sname as 姓名, score.cno as 课程编号, score.Degree as 成绩 from student, score where student.Sno=score.Sno; ``` #### 内连接 ```mysql # 内连接: 表1 inner join 表2 on 表1.id=表2.id # 表1.id于表2.id 描述同一显示事物 select student.Sname as 姓名, score.cno as 课程编号, score.Degree as 成绩 from student inner join score on student.Sno=score.Sno; # 如果三张表: 表1 inner join 表2 on 表1.id=表2.id inner join 表3 on 表2.id=表3.id ``` #### 外连接 ```mysql # 左外连接: 表1 left join 表2 on 表1.id-表2.id -- 返回左表中的所有数据,对应右表不存在的数据,以nul1的形式返回。 # 右外连接: 表1 right join 表2 on 表1.id-表2.id -- 返回右表中的所有数据,对应左表中不存在的数据,以nul1形式返回。 # 哪些学生没有选修课程的 select student.Sname as 姓名 from student left join score on student.sno=score.sno where student.degree is NULL; ``` ![](https://img.081024.xyz/6-MySQL-20240602021704838.jpg) ![](https://img.081024.xyz/6-MySQL-20240602021732743.jpg) #### 子查询 ```mysql # 子查询:一个查询语句中,嵌套另一个查询语句。 -- 多行子查询: in 和 not in -- 单行子查询: >, < , >=, <=, !=, 不等于也可以写成<> # 哪些学生没有选修课程的 select * from student where sno not in (select sno from score); # 查询成绩表中成绩最高的学生 select * from student where student.sno=score.sno and score.degree = (select max(degree) from score); ```