分类 | 说明 |
---|---|
DDL | 数据定义语言,用来定义数据库对象(数据库,表,字段) |
DML | 数据操作语言,用来对数据库表中的数据进行增删改 |
DQL | 数据查询语言,用来查询数据库中表的记录 |
DCL | 数据控制语言,用来创建数据库用户、控制数据库的访问权限 |
-- 查询所有数据库
show databases;
-- 查询当前数据库
select database();
creat database [if not exists] 数据库名 [default charset 字符集][collate 排序规则];
drop database [if exists]数据库名
use 数据库名
-- 查询挡墙数据库所有表
show tables;
-- 查询表结构
desc 表名
-- 查询指定表的建表语句
show create table 表名;
create table 表名(
字段1 字段1类型 [comment 字段1注释],
字段2 字段2类型 [comment 字段2注释],
...
字段n 字段n类型 [comment 字段n注释]
);
-- 添加字段
alter table 表名 add 字段名 类型 [comment 注释] [约束];
-- 修改数据类型
alter table 表名 modify 字段名 新数据类型;
-- 修改字段名和字段类型
alter table 表名 change 旧字段名 新字段名 类型 [comment 注释] [约束];
-- 删除字段
alter table 表名 drop 字段名;
-- 修改表名
alter table 表名 rename to 新表名;
-- 删除表
drop table [if exists] 表名;
-- 1.给指定字段添加数据
insert into 表名(字段1,字段2,...) values(值1,值2,...);
-- 2.给全部字段添加数据
insert into 表名 values(值1,值2...);
-- 3.批量添加数据
insert into 表名 (字段名1,字段名2,...) values (值1,值2...),(值1,值2...);
/* 插入数据时,指定数据的字段顺序需要与值的顺序是一一对应的
字符串和日期型数据应该包含在引号中
插入的数据大小,应该在规定的范围内*/
update 表名 set 字段名1 = 值1,字段名2 = 值2,...[where 条件];
/* update语句的条件可以有也可以没有,如果没有,则修改整张表的所有数据*/
delete from 表名 [where 条件];
/* delete语句的条件可以有也可以没有,如果没有,则删除整张表的所有数据
delete语句不能删除某一个字段的值 (可以使用update)*/
-- DQL语法
select
字段列表
from
表名列表
where
条件列表
group by
分组字段列表
having
分组后条件列表
order by
排序字段列表
limit
分页参数;
-- 1.查询多个字段
select 字段1,字段2,字段3...from 表名;
select * from 表名;
-- 2.设置别名
select 字段1 as 别名1,字段2 as 别名2... from 表名;
-- 3.去除重复记录
select distinct 字段列表 from 表名;
select 字段列表 from 表名 where 条件列表;
将一列数据作为一个整体,进行纵向计算
常用聚合函数
函数 | 功能 |
---|---|
count | 统计数量 |
max | 最大值 |
min | 最小值 |
avg | 平均值 |
sum | 求和 |
select 聚合函数(字段列表)from 表名;
select 字段列表 from 表名 [where 条件] group by 分组字段名 [having 分组后过滤条件];
注意: where与having区别
select 字段列表 from 表名 order by 字段1 排序方式1,字段2,排序方式2;
注意:如果是多字段排序,当第一个字段相同时,才会根据第二个字段进行排序
select 字段列表 from 表名 limit 起始索引,查询记录数;
注意:
-- 1.查询年龄为20,21,22岁的女性员工信息
select * from emp where gender = '女' and age in(20,21,22);
-- 2.查询性别为男,并且年龄在 20-40岁以内的姓名为三个字的员工
select * from emp where gender='男' and age between 20 and 40and name like'---';
-- 3.统计员工表中,年龄小于60岁的,男性员工和女性员工的数量
select gender,count(*) from emp where age <60 group by gender;
-- 4.查询所有年龄小于等于35岁员工的姓名和年龄,并对查询结果按年龄升序排序,如果年龄相同按入职时间降序排序
select name age from emp where age <=35 order by age,entrydate desc;
-- 5.查询性别为男,且年龄在20-40的前五个员工信息,对查询结果按年龄升序排序,年龄相同按入职时间升序排序
select * from emp where gender = '男' and age between 20 and 40 order by age asc,entrydate asc limit 5;
用来管理数据库用户、控制数据库的访问权限
-- 1. 查询用户
USE mysql;
select * from user;
-- 2.创建用户
create user '用户名'@'主机名' identified by '密码';
-- 3.修改用户密码
alter user '用户名'@'主机名' identified with mysql_native_password by '新密码';
-- 4.删除用户
drop user '用户名'@'主机名';
-- 1.查询权限
show grants for '用户名'@'主机名';
-- 2. 授予权限
grant 权限列表 on 数据库名.表名 to '用户名'@'主机名';
-- 3. 撤销权限
revoke 权限列表 on 数据库名.表名 to '用户名'@'主机名';
函数 | 功能 |
---|---|
concat(s1,s2,…sn) | 字符串拼接 |
lower(str) | 将字符串全部转换为小写 |
upper(str) | 将字符串全部转换为大写 |
lapd(str,n,pad) | 左填充,用字符串pad对str的左边进行填充,达到n个字符串长度 |
rpad(str,n,pad) | 右填充,用字符串pad对str的右边进行填充,达到吗、n个字符串长度 |
trim(str) | 去掉字符串头部和尾部的空格 |
substring(str,start,len) | 返回从字符串str的start位置起的len个长度字符 |
函数 | 功能 |
---|---|
ceil(x) | 向上取整 |
floor(x) | 向下取整 |
mod(x) | 返回x/y的模 |
rand() | 返回0~1内的随机数 |
round(x,y) | 求参数x的四舍五入值,保留y位有效数字 |
函数 | 功能 |
---|---|
curdate() | 返回当前日期 |
curtime() | 返回当前时间 |
now() | 返回当前时间和日期 |
year(date) | 获取指定日期的年份 |
month(date) | 获取指定日期的月份 |
day(date) | 获取指定日期的日期 |
date_add(date,interval expr type) | 返回一个日期/时间值加上一个时间间隔expr后的时间值 |
datadiff(date1,date2) | 返回起始时间date1和结束时间date2之间的天数 |
函数 | 功能 |
---|---|
if(value,t,f) | 如果value为true,返回t,否则返回f |
ifnull(value1,value2) | 如果value1不为空,则返回value1,否则返回value2 |
case when [ val1] then [ res1]…else [ default] end | 如果val1为true,返回res1,…否则返回defult默认值 |
case[ expr1] when [ val1] then [ res1] …else [default] end | 如果expr的值等于val1,返回res1,…否则返回default默认值 |
1.概念:约束是作用于表中字段的规则,用于限制存储在表中的数据
2.目的:保证数据库中数据的正确、有效性和完整性
3.分类
约束 | 描述 | 关键字 |
---|---|---|
非空约束 | 限制该字段的数据不能为空 | NOT NULL |
唯一约束 | 保证该字段的所有数据都是唯一的,不重复的 | UNIQUE |
主键约束 | 主键是一行数据的唯一标识,要求非空且唯一 | PRIMARY KEY |
默认约束 | 保存数据时,如果未指定该字段的值,则采用默认值 | DEFAULT |
检查约束 | 保证字段值满足某一个条件 | CHECK |
外键约束 | 用来让两张表之间建立连接,保证数据一致性和完整性 | FOREIGN KEY |
概述:从多张表中查询数据
多表关系:一对多、多对多、一对一
笛卡尔积:指在数学中,两个集合A和B的所有组合情况(在多表查询时,需要消除无效的笛卡尔积)
-- 隐式内连接
select 字段列表 from 表1,表2 where 条件:
-- 案例1 查询每一个员工的姓名,及关联的部门的名称
select e.name,d.name from emp e,dept d where e.dept_id = d.id;
-- 显式内连接
select 字段列表 from 表1 [inner] join 表2 on 连接条件...;
-- 案例2 查询每一个员工的姓名,及关联的部门名称
select e.name,d.name from emp e inner join dept d on e.dept_id = d.id;
-- 左外连接
select 字段列表 from 表1 left [outer] join 表2 on 连接条件;
-- 案例 查询emp表所有的数据,和相应的部门信息
select e.*,d.name from emp e left join dept d on e.dept_id = d.id;
-- 右外连接
select 字段列表 from 表1 right [outer] join 表2 on 连接条件;
-- 案例 查询dept表的所有数据,和相应的部门信息
select e.*,d.* from emp e right join dept d on e.dept_id = d.id;
自连接查询,可以是内连接查询,也可以是外连接查询
select 字段列表 from 表A 别名A join 表A 别名B on 条件...;
-- 案例 查询所有员工emp及其领导的名字emp,如果员工没有领导,也需要查询出来
select * from emp e1 left join emp e2 on e1.managerid = e2.id;
对于union查询,就是把多次查询的结果合并起来,形成一个新的查询结果集
select 字段列表 from 表A...
union[all]
select 字段列表 from 表B ...;
1.对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致
2.union all会将全部的数据直接合并在一起,union会对合并之后的数据进行去重
SQL语句中嵌套SELECT语句,称为嵌套查询,又称子查询
select * from t1 where column=(select column1 from t2);
子查询外部的语句可以是 insert、update、delete、select的任何一个
根据子查询的的结果不同,分为
标量子查询(查询结果为单个值)
列子查询 (查询结果为一列)
行子查询(查询结果为一行)
表子查询(查询结果为多行多列)
子查询返回的结果是单个值(数字、字符串、日期等),最简单的形式
常用操作符:= < > >= <=
返回的结果是一列(可以是多行)
常用操作符:in 、not in、any、some、all
操作符 | 功能 |
---|---|
in | 在指定的集合范围之内,多选一 |
not in | 不在指定的范围之内 |
any | 子查询返回列表中,有任意一个满足即可 |
some | 与any等同,使用some的地方都可以使用any |
all | 子查询返回列表的所有值都必须满足 |
子查询的结果是一行(可以是多列)
常用操作符:=、<>、in、not in
子查询返回的结果是多行多列
常用操作符:in
--1.查询员工的姓名、年龄、职位、部门信息(隐式内连接)
select e.name,e.age,d.job,d.name from emp e,dept d where e.dept_id = d.id;
--2.查询年龄小于30岁的员工的姓名、年龄、职位、部门信息(显式内连接)
select e.name,e.age,e.job,d.name from emp e inner join dept d on e.dept_id=d.id where e.age <30;
--3.查询拥有员工的部门id,部门名称
select distinct d.name,d.name from emp e,dept t where e.dept_id = d.id;
--4.查询所有年龄大于40岁的员工,及其归属的部门名称,如果没有归属部门,也需要展示出来
select e.*,e.name from emp e left join dept d on e.dept_id = d.id where e.age >40;
--5.查询所有员工工资等级
select e.*,s.grade from emp e,salgrade s where e.salary >=s.losary and e.salary <=s.hisal
--6.查询研发部所有员工的信息及工资等级
-- 连接条件:emp.salary >= s.losary and e.salary <=s.hisal,emp.dept_id = dept.id
select e.*,s.grade from emp e,dept d,sargrade s where e.dept_id = d.id and (emp.salary >= s.losary and e.salary <=s.hisal) and e.name = '研发部';
--7.查询研发部的平均工资
select avg(e.salary) from emp e,dept d where e.dept_id = d.id and d.name = '研发部';
--8.查询工资比灭绝 高的员工信息
select * from emp where salary >(select sarlary from emp where name = '灭绝');
--9.查询比平均薪资高的员工信息
select * from emp where salary >(select avg(sarlary) from emp);
--10.查询低于本部门平均工资的员工信息
select * from emp e2 where e2.salary < (select avg(e1.salary) from emp e1 where e1.dept_id = e2.dept_id);
--11.查询所有的部门信息,并统计部门的员工人数
select d.id,d.name,(select count(*) from emp e where e.dept_id = d.id) '人数'from dept d;
--12.查询所有学生的选课情况,展示出学生名称,学号,课程名称
--student,course, student_course三张表
--连接条件:studenet.id = student_course.studentid,course.id = student_course.courseid
select s.name,s.no,c.name from student s,student_course sc,course c where s.id = sc.studentid and sc.courseid = c.id;
事务是一组操作的集合,他是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
-- 查看事务的自动提交方式 1 自动提交 0 手动提交
select @@autocommit;
-- 修改事务提交方式为 手动提交
set @@autocommit = 0;
start transaction;
commit;
rollback;
案例 转账操作
select @@autocommit;
set @@autocommit = 0;
-- 转账操作(张三给李四转1000)
-- 1. 查询张三账户余额
select * from account where name = '张三';
-- 2.将张三账户余额-1000
update account set money = money-1000 where name = '张三';
程序执行报错。。。 -- 若抛出异常
-- 3.将李四的账户余额+1000
update account set money = money+1000 where name = '李四';
-- 提交事务
commit;
-- 回滚事务
rollback;
问题 | 描述 |
---|---|
脏读 | 一个事务读到另外一个事务还没提交的数据 |
不可重复读 | 一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读 |
幻读 | 一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现了这行数据已经存在,好像出现了‘幻影’ |
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Read uncommitted | √ | √ | √ |
Read committed | × | √ | √ |
Repeatable Read(默认) | × | × | √ |
Serializable | × | × | × |
从上到下,隔离级别越来越高,性能越来越差,数据越来越安全
Read uncommitted:是事务中最低的级别,在该级别下的事务可以读取到其他事务中未提交的数据,这种读取的方式也被称为脏读(Dirty Read)。简而言之,脏读是指一个事务读取了另外一个事务未提交的数据。
例如,Alex 要给 Bill 转账100元购买商品,Alex开启事务后转账,但不提交事务,通知Bill来查询,如果Bill的隔离级别较低,就会读取到Alex的事务中未提交的数据,发现Alex确实给自己转了100元,就给Alex发货。等Bill发货成功后,Alex将事务回滚,Bill就会受到损失,这就是脏读造成的。
Read committed:是大多数 DBMS (如 SQL Server、Oracle) 的默认隔离级,但不包括MySQL。
在该隔离级下只能读取其他事务已经提交的数据,避免了脏读数据的现象。但是在该隔离级别下,会出现不可重复读(NON-REPEATABLE READ)的问题。
不可重复读是指在一个事务中多次查询的结果不一致,原因是查询的过程中数据发生了改变。
例如,在网站后台统计所有用户的总金额,第1次查询Alex有900元,为了验证查询结果,第2次查询Alex有800元,两次查询结果不同,原因是第2次查询前Alex取出了100元。
Repeatable Read:是MySQL的默认事务隔离级,它解决了脏读和不可重复读的问题,确保了同一事务的多个实例在并发读取数据时,会看到同样的结果。但在理论上,该隔离级会出现幻读(PHANTOM READ)的现象。
幻读又被称为虚读,是指在一个事务内两次查询中数据条数不一致,幻读和不可重复读有些类似,同样发生在两次查询过程中。不同的是,幻读是由于其他事务做了插入记录的操作,导致记录数有所增加。不过,MySQL的InnoDB存储引擎通过多版本并发控制机制解决了幻读的问题。
例如,在网站后台统计所有用户的总金额时,当前只有两个用户,总金额为2000元,若在此时新增一个用户,并且存入1000元,再次统计时发现总金额变为3000元,造成了幻读的情况。
Serializable:是最高级别的隔离级,它在每个读的数据行上加锁,使之不会发生冲突,从而解决了脏读、不可重复读和幻读的问题。但是由于加锁可能导致超时(Timeout) 和 锁竞争(Lock Contention)现象,因此 SERIALIZABLE 也是性能最低的一种隔离级。除非为了数据的稳定性,需要强制减少并发的情况时,才会选择此种隔离级。
-- 查看事务隔离级别
select @@TRANSACTION_ISOLATION;
-- 设置事务隔离级别
set [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {Read uncommitted|Read committed|Repeatable Read|Serializable}
论上,该隔离级会出现幻读(PHANTOM READ)的现象。
幻读又被称为虚读,是指在一个事务内两次查询中数据条数不一致,幻读和不可重复读有些类似,同样发生在两次查询过程中。不同的是,幻读是由于其他事务做了插入记录的操作,导致记录数有所增加。不过,MySQL的InnoDB存储引擎通过多版本并发控制机制解决了幻读的问题。
例如,在网站后台统计所有用户的总金额时,当前只有两个用户,总金额为2000元,若在此时新增一个用户,并且存入1000元,再次统计时发现总金额变为3000元,造成了幻读的情况。
-- 查看事务隔离级别
select @@TRANSACTION_ISOLATION;
-- 设置事务隔离级别
set [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {Read uncommitted|Read committed|Repeatable Read|Serializable};
以上为Mysql基础篇的知识,从通用语法到DDL、DCL、DML、DQL语句,函数、约束、多表查询以及事务。此篇内容是本人在学习MySQL之余总结的学习笔记,可供学习参考,可能会存在些许遗漏获错误,欢迎大家批评指正,剩余的进阶篇内容,数据库编程、引擎、、索引、锁等内容会在学习完之后持续更新。希望大家一起学习进步!