客户端和数据库操作
- 登录
mysql -uroot -p - 查看当前的数据库版本
select version(); - 显示所有数据库
show databases; - 创建数据库
create [if not exists] database 数据库名 character set 字符编码集 collate 排序规则; - 选择数据库
use 数据库名 - 查看当前选择了哪个数据库
select database(); - 删除数据库
drop [if exists] database 数据库名;//非常危险的操作 - 查看警告信息
show warnings; - 退出
quit\exit
表操作
- 查看当前数据库中有哪些表
show tables; - 创建一张新表
create table 表名(列表/字段名 数据类型[,列表/字段名 数据类型 ...]); - 查看表结构
desc 表名; - 删除表
drop 表名;//非常危险的操作
CRUD 增删改查
新增 - 插入
insert into 表名 [(列名[,列名...])] values (值[,值...]);
- 指定了多少列名,就需要指定多少值,值与列名一一对应
- 不指定列名,值的顺序与个数和表中所有的列一一对应
查询操作
a. 全列查询
select * from 表名; // 不加限制的查询会把表中所有的数据都查出来
b. 指定列查询
select 列名[,列名...] from 表名; // 推荐使用
c. 列为表达式的查询
select 列名表达式 from 表名;
d. 别名查询
select 列名表达式 [as] 别名 from 表名; // 别名中如果包含空格,需要用单引号引起来
e. 去重查询
select distinct 列名[,列名...] from 表名; // 如果列名有多个,去重时只有所有的列都相等,才会判定为重复,才会去重
f. 排序查询
select 列名[,列名...] from 表名 order by 列名 asc|desc; //asc 升序 desc 降序
g. 条件查询
select 列名[,列名...] from 表名 where 列名(表达式) 比较|逻辑运算符
h. 区间查询
where 列名 between 开始条件 and 结束条件; // 等价于 开始条件 <= 列的值 <= 结束条件
i. 模糊查询
select * from 表名 where 列名 like '值%'; //% 匹配任意字符 _ 匹配单个字符
j. 分页查询
select * from 表名 where 条件 order by 列名 asc|desc limit num; // 查询前 num 条记录
select * from 表名 where 条件 order by 列名 asc|desc limit start, num; // 从第 start 条开始,向后查 num 条
select * from 表名 where 条件 order by 列名 asc|desc limit num offset start; // 从第 start 条开始,向后查 num 条
更新
update 表名 set 列名 = 值 where 条件 order by 子句 limit num; // 如果不指定条件和 limit 的数量就会更新整表
删除
delete from 表名 where 条件 order by 子句 limit num; // 如果不指定条件和 limit 的数量就会删除整表中的数据
数据库约束
- 非空约束:
NOT NULL标记一个字段是否可以为空,指定了这个约束,字段就不能为空 - 唯一约束:
UNIQUE标记一个字段的内容在当前列中唯一,不能重复,但是可以为NULL - 主键约束:
PRIMARY KEY,在约束的方式上相当于NOT NULL + UNIQUE - 默认约束:
DEFAULT当一个字段没有指定值时 (为NULL时),不指定列的值的时,就用默认值去填充该列 - 外键约束:
FOREIGN KEY一个表中的字段与另一个表中的主键建立关联关系,当对表中的数据进行增删改的时候数据库会帮我们进行检查
表的设计
三大范式
- 第一范式:要求表中的每一个列不可再分,有一个简单的方法,数据库中提供的数据类型里可以描述这个字段
- 第二范式:在满足第一范式的前提下消除部分函数依赖,字段只依赖于复合主键中的某一个列(多个候选键),如果有一个字段只依赖于复合主键中的某一个列,那么就需要把这个列剔除,单独建表,不满足第二范式的情况下会出现一些数据异常:数据冗余、更新异常,删除异常,新增异常
- 第三范式:在第二范式的基本下,消除传递依赖
关系模型
- 一对一关系:各自先建立各自的表,在其中一张表中加一个字段完成对另一张表的引用 (建立关系)
- 一对多关系:各自先建立各自的表,在这一方设置一个主键,在多这一方加一个字段,两表建立引用关系
- 多对多关系:各自先建立各自的表,另外新加一张关系表
聚合函数
COUNT(列)统计结果集的条数SUM(列)求和AVG(列)求平均值MIN(列)最小值MAX(列)最大值
GROUP BY 分组查询
对某一个字段进行分组操作,分组后可以结合聚合函数进行一些运算
HAVING 子句
对GROUP BY的结果进行过滤
联合查询(表连接查询)
1. 内连接
sql
select * from table1, table2 where table1.xxx = table2.xxx;
select * from table1 join table2 on table1.xxx = table2.xxx;
select * from table1 inner join table2 on table1.xxx = table2.xxx;
表连接的执行过程:
- 先计算参与表连接的笛卡尔积
- 通过连接条件过滤无效数据
- 加入查询条件得到想要的结果行
- 精减列名得到最终想要查询的列
2. 外连接,分为左外连接和右外连接
sql
select * from table1 left join table2 on table1.xxx = table2.xxx;
select * from table1 right join table2 on table1.xxx = table2.xxx;
左外连接以左表为基准,左表中的所有的数据全部显示,右表中没有对应的记录用NULL去填充
右外连接以右表为基准,右表的表中所有的数据全部显示,左表中没有对应的记录用NULL去填充
主要应用在两张表数据不一致的场景里
3. 自连接
sql
select * from table1 t1, table1 t2 where t1.xxx = t2.xxx;
把行转换成列,在查询的时候可以使用WHERE条件进行过滤,实现行与行之间的比较
4. 子查询
- 单行子查询:
select * from table1 where id = (select id from table2 where clo = xxx); - 多行子查询:
select * from table1 where id IN (select id from table2 where clo = xxx); - 内层查询的结果做为外层查询的条件,把多条语句合并为一条执行
- 子查询可以无限嵌套,层数过多会影响效率
5. 合并查询
sql
select * from table1 union select * from table2;
select * from table1 union all select * from table2;
作用是把两个结果集中合并成一个返回
注意:合并查询时多个查询的查询列表必须匹配,MYSQL 不对结果做校验,写的时候务必注意
错误演示
sql
mysql> select student_id, name from student union select class_id, name from class;
| student_id | name |
|---|---|
| 1 | 黑风李逹 |
| 2 | 精英老祖 |
| 3 | 问答 |
| 4 | 盲盒 |
| 5 | 不想毕业 |
| 6 | 好好说 |
| 7 | 1 |
| 8 | 老外学中文 |
| 1 | 计算机 2019 级 1 班 |
| 2 | 计算机 2019 级 3 班 |
| 3 | 计应 2018 级 3 班 |
| 11 rows in set (0.00 sec) |
6. 一条 SQL 语句中各部分的执行顺序
自己构造一条 SQL,不一定可以执行成功,但是相关的关键字都包含
sql
SELECT DISTINCT
s.id,
name,
AVG(age)
FROM
student
JOIN
class ON student.class_id = class.id
WHERE
class_id = 1
GROUP BY
student.id
HAVING
AVG(age) > 0
ORDER BY
student.id ASC
LIMIT 100;
执行顺序:FROM -> JOIN ON -> WHERE -> GROUP BY -> HAVING -> SELECT -> DISTINCT -> ORDER BY -> LIMIT